【问题标题】:How to multi-callback a promise in AngularJs with $q?如何使用 $q 在 AngularJs 中多次回调一个 Promise?
【发布时间】:2015-10-01 07:50:33
【问题描述】:

我正在使用下面的代码来简化后端请求,但我没有掌握如何调用成功方法或错误方法。

如何才能达到代码中注释的预期行为?

app.factory('REST', function ($http, $q, sweetAlert) { 返回 { 加载:功能(模块,动作,数据){ var deferred = $q.defer(); var promise = deferred.promise; $http .post('/api/'+module+'.php?action='+action, data) .success(函数(数据){ 如果(数据。错误) { sweetAlert.swal({ 标题:“错误”, 文本:data.error, 类型:“警告” }); //在这里我想调用 .error(details) } 别的 deferred.resolve(data.result); }).error(函数 () { //在这里我想调用 .error(details) }); promise.success = 函数(fn){ 承诺.then(fn); 回报承诺; } 回报承诺; } }; });

这是使用上述代码的代码:

$scope.login = function () {
    $scope.loading = true;
    var payload = {'credentials': $scope.logindata};
    REST.load('access', 'login', payload).success(function(data) {
        if(data.redirect)
            $state.go(data.redirect);
        $scope.loading = false;
    }).error(function(data) { //THIS SHOULD BE CALLED
        $scope.loading = false;
    });
}

【问题讨论】:

  • 常规承诺没有任何成功()/错误()功能。它们有一个 then() 和一个 catch() 函数。这些是您的客户端代码应该调用的。阅读blog.ninja-squad.com/2015/05/28/angularjs-promises
  • 你的意思是你想打电话给.reject(),而不是.error()

标签: angularjs callback promise q deferred


【解决方案1】:

更新你的代码如下

app.factory('REST', function ($http, $q, sweetAlert) {
   return {
       load: function (module, action, data) {
              var deferred = $q.defer();                  
                  $http.post('/api/'+module+'.php?action='+action, data)
                          .success(function (data) {
                              if(data.error)
                              {
                                  sweetAlert.swal({
                                      title: "Error",
                                      text: data.error,
                                      type: "warning"
                                  });     
                                 //HERE I WANT TO CALL .error(details)                                
                                 deferred.reject(data.error);
                              }
                              else{
                                deferred.resolve(data.result);
                              }

                         })
                         .error(function (error) {
                              //HERE I WANT TO CALL .error(details)
                              deferred.reject(error);   
                          });

               return defferred.promise;
          }
   };
});

为你的控制器

 $scope.login = function () {
     $scope.loading = true;
     var payload = {'credentials': $scope.logindata};
     REST.load('access', 'login', payload).then(
       function(data) {
         if(data.redirect)
             $state.go(data.redirect);
             $scope.loading = false;
       },
       function(error) {
          $scope.loading = false;
       });
   }

【讨论】:

    【解决方案2】:

    首先,我强烈建议您不要将.success 附加到您要返回的承诺中。这不符合 Promises/A,它与 .then 的细微差别(由 $http 实现)会引起很多混乱。只是回报一个纯粹的承诺。

    除此之外,还有几点需要注意:

    1) 你不需要另一个$q.deferdeferred.resolve() - 只需链接到$httpreturn 的原始承诺即可。 (见deferred anti-pattern

    2) 拒绝一个承诺——也就是说,导致.catch(不是.error——关于细微差别见上文)触发——你应该返回$q.reject()

    以上所有内容都会产生以下结果:

    app.factory('REST', function($http, $q, sweetAlert){
      return {
        load: function(module, action, data) {
          // this "return" returns the promise of $http.then
          return $http.post('/api/' + module + '.php?action=' + action, data)
            .then(function(response) {
              var data = response.data; // .then gets a response, unlike $http.success
    
              if (data.error) {
                sweetAlert.swal({
                  title: "Error",
                  text: data.error,
                  type: "warning"
                });
    
                //HERE I WANT TO CALL .error(details)
    
                return $q.reject(data.error);
              }
    
              return data.result; // what you would have "resolved"
            });
        }
      };
    })
    

    然后,正如我上面所说,使用 .then/.catch,就像使用 Promise 一样:

    $scope.login = function () {
        $scope.loading = true;
        var payload = {'credentials': $scope.logindata};
        REST.load('access', 'login', payload)
            .then(function(data) {
              if(data.redirect)
                 $state.go(data.redirect);
              $scope.loading = false;
            })
            .catch(function(error) {
              $scope.loading = false;
            });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-04
      • 1970-01-01
      • 1970-01-01
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多