【问题标题】:How to pass data from one asynchronous to another asynchronous function in AngularJS如何在AngularJS中将数据从一个异步函数传递到另一个异步函数
【发布时间】:2019-09-26 19:46:05
【问题描述】:

如何将全局变量值从一个函数传递给另一个函数?

我有 2 个全局变量:

$scope.genewtId = null;
$scope.data1 = null;

我有 2 个角函数,如下所示:

$scope.getID = function() {
    Service1.getId("abc").then(function(response){
        $scope.genewtId = response.data[0].Id;
        console.log($scope.genewtId);

    }, function(error){
        console.log(error.statusText);
    });
};

$scope.getDetails = function() {
    Service2.getDetails($scope.genewtId).then(function(response){
        // here response is having an error
        $scope.data1 = response.data;
        console.log($scope.data1.toString());
    }, function(error){
        console.log(error.statusText);
    });
};

当我将 $scope.genewtId 的值从一个函数传递到另一个函数时,我得到一个错误

消息:“无法将 'java.lang.String' 类型的值转换为所需类型 'java.lang.Integer';嵌套异常是 java.lang.NumberFormatException:对于输入字符串:“null””

但是,console.log($scope.genewtId); 正在返回一个值 787651,这意味着它不为空。

请建议是否可以使用$rootScope.$broadcast实现

【问题讨论】:

    标签: javascript angularjs angular-promise angularjs-service angularjs-http


    【解决方案1】:

    我能想到的唯一原因是因为asynchronous调用promises。发生了什么事:

    不知何故,您在$scope.genewtId 的值在Service1.getId("abc").then 的承诺完成之后设置之前调用Service2.getDetails($scope.genewtId),因此该值仍然是null

    试试:

    $scope.getID = function(isCalledAfterDetails) {
        Service1.getId("abc").then(function(response){
            $scope.genewtId = response.data[0].Id;
            console.log($scope.genewtId);
            if(isCalledAfterDetails && $scope.genewtId !== null){
                $scope.getDetails();
            }
    
        }, function(error){
            console.log(error.statusText);
        });
    };
    
    $scope.getDetails = function() {
        if($scope.genewtId === null){
            $scope.getID(true);
        }else{
            Service2.getDetails($scope.genewtId).then(function(response){
                // here response is having an error
                $scope.data1 = response.data;
                console.log($scope.data1.toString());
            }, function(error){
                console.log(error.statusText);
            });
        }
    
    };
    

    即使这种方法有效,我强烈建议您以更好的方式实现函数调用,因为$scope.getDetails() 依赖于$scope.getID() 来设置$scope.genewtId 的值。

    如果您需要有关如何实现它的建议,请使用用例和更多代码更新问题

    更新

    $scope.getID = function() {
        Service1.getId("abc").then(function(response){
            $scope.genewtId = response.data[0].Id;
            $scope.getDetails();
        }, function(error){
            console.log(error);
        });
    };
    
    $scope.getDetails = function() {
            Service2.getDetails($scope.genewtId).then(function(response){
                // here response is having an error
                $scope.data1 = response.data;
                console.log($scope.data1.toString());
            }, function(error){
                console.log(error.statusText);
            });        
    };
    

    使用服务

    service.js

    getDetails = function(id){
        var deferred = $q.derfer();
        $http.get('/user/'+id).then(function(response){
            var newId = response.data[0].Id;
            $http.get('/user/details'+newId).then(function(details){
                deferred.resolve(details)
            })
        })      
        return deferred.promise;
    }
    

    controller.js

    $scope.getDetails = function() {
            MySvc.getDetails("abc").then(function(response){
                console.log(response) // your details here
            }, function(error){
                console.log(error.statusText);
            });        
    };
    

    【讨论】:

    • 请建议是否可以使用$rootScope.$broadcast实现
    • @meallhour :这些函数是如何依赖的? 1. 得到getID 的ID 后,你想打电话给getDetails 吗? 2. 或者它们可以存在于单独的controller 中吗?使用事件意味着它们相互依赖并且存在于单独的controller 中。所以,他们必须互相通知他们的变化
    • 1.从getIDYes this is true得到ID后是否要调用getDetails
    • 它们可以存在于单独的控制器中吗? They are existing in the same controller and not separate controler
    • @meallhour 检查我更新的代码。在Service1.getId() 解决后调用getDetails()。您还可以在同一服务中同时移动逻辑 getIdgetDetails,并使用 IDDETAILS 提供单个响应
    【解决方案2】:

    似乎异常来自服务器端。

    无法将“java.lang.String”类型的值转换为所需类型 'java.lang.Integer';嵌套异常是 java.lang.NumberFormatException:对于输入字符串:“null”

    由于console.log(error.statusText);,它正在控制台上打印

    在API中使用该值时需要验证逻辑。

    【讨论】:

      【解决方案3】:

      这两个服务的承诺必须是chained

      修改第一个函数以返回一个承诺:

      $scope.getID = function() {
          return Service1.getId("abc").then(function(response){
              $scope.genewtId = response.data[0].Id;
              console.log($scope.genewtId);
              return response.data[0].Id;
          }, function(error){
              console.log(error.statusText);
              throw error;
          });
      };
      

      修改第二个函数,使其既返回承诺又接受参数:

      $scope.getDetails = function(id) {
          var genewtID = id || $scope.genewtId;
          return Service2.getDetails(genewtId).then(function(response){
              $scope.data1 = response.data;
              console.log($scope.data1.toString());
              return response.data;
          }, function(error){
              console.log(error.statusText);
              throw error;
          });
      };
      

      然后chain两个promise:

      var promise = $scope.getId();
      
      var promise2 = promise.then(function(id) {
                         return $scope.getDetails(id);
                     });
      
      var promise2.then(function(data) {
           console.log(data);
      }).catch(function(error) {
           console.log(error);
      });
      

      通过使用getId 承诺的.then 方法,代码在向getDetails 发出请求之前等待id 值从服务器到达。

      因为调用promise 的.then 方法会返回一个新的派生promise,所以很容易创建一个promise 链。可以创建任意长度的链,并且由于可以使用另一个 Promise 来解决一个 Promise(这将进一步推迟其解决方案),因此可以在链中的任何点暂停/推迟对 Promise 的解决。

      有关详细信息,请参阅

      【讨论】:

        猜你喜欢
        • 2018-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-14
        • 1970-01-01
        • 2020-09-18
        • 1970-01-01
        相关资源
        最近更新 更多