如何使用 $q 在 AngularJs 中多次回调承诺?

xsp*_*ial 2 callback promise deferred angularjs q

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

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

 
app.factory('REST', function ($http, $q, sweetAlert) {

    返回 {
        负载:功能(模块,动作,数据){
            var deferred = $q.defer();
            var promise = deferred.promise;         
            $http
            .post('/api/'+module+'.php?action='+action, data)
            .成功(功能(数据){

                如果(数据错误)
                {
                    sweetAlert.swal({
                        标题:“错误”,
                        文本:数据错误,
                        类型:“警告”
                    });
                //这里我想调用 .error(details)
                }
                别的
                    deferred.resolve(data.result);

                        }).错误(函数(){
                //这里我想调用 .error(details)
            });

            promise.success = 函数(fn){
                承诺。然后(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;
    });
}
Run Code Online (Sandbox Code Playgroud)

New*_*Dev 5

首先,我强烈建议您不要执着.success于您要返回的承诺。这不符合 Promises/A,并且它与.then(由 实现的$http)的细微差别引起了很多混淆。只返回一个纯粹的承诺。

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

1)你不需要另一个$q.deferdeferred.resolve()- 只需链接到最初的承诺$httpreturn由此产生的承诺。(见延迟反模式

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"
        });
    }
  };
})
Run Code Online (Sandbox Code Playgroud)

然后,正如我上面所说的,像使用 promise 一样使用.then/ .catch

$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;
        });
}
Run Code Online (Sandbox Code Playgroud)