【问题标题】:How can I extend $q promise in Angularjs with a .success and .error如何使用 .success 和 .error 在 Angularjs 中扩展 $q 承诺
【发布时间】:2013-05-23 17:29:34
【问题描述】:

我在 AngularJS 的自定义服务中编写了这个小代码。

为我服务:

        var deferred = $q.defer();
        var promise = deferred.promise;

        deferred.resolve('success');
        deferred.reject('error');

        /* Handle success and error */
        promise.success = function(fn) {

            promise.then(function(response) {

                fn(response);

            });

            return promise;
        };

        promise.error = function(fn) {

            promise.then(null, function(response) {

                fn(response);

            });

            return promise;
        };

在我的控制器中:

        promiseService.myPromise()
            .success(function(data){

                $scope.success= data;

            })
            .error(function(data){

                $scope.error = data;

            });

我只是从承诺($q 服务)中处理成功和错误。我在很多其他服务中都需要此代码,因此我将直接使用自定义扩展 $q 服务。

所以我想在我的服务中使用这样的东西:

    var deferred = myPromiseService.$qCustom.defer();
    var promise = deferred.promise;

    deferred.resolve('success');
    deferred.reject('error');

    return promise;

有什么想法吗?我找到了一些在 Angularjs 中扩展过滤器的解释,我的问题是找到扩展 $q 的所有功能并添加我的自定义的好方法。

我从类似的东西开始,开箱即用地处理 $q :

angular.module('myApp').service('myPromiseService', function($q){

  $qCustom = $q;  

});

【问题讨论】:

    标签: angularjs extend overriding promise angularjs-service


    【解决方案1】:

    这是一个完整的解决方案,从@jessegavin 停止的地方开始。

    var myApp = angular.module("myApp", []);
    
    myApp.config(function ($provide) {
    
      $provide.decorator('$q', function ($delegate) {
        var defer = $delegate.defer;
        $delegate.defer = function () {
          var deferred = defer();
          deferred.promise.success = function (fn) {
            deferred.promise.then(function(response) {
              fn(response.data, response.status, response.headers);
            });
          return deferred.promise;
          };
          deferred.promise.error = function (fn) {
            deferred.promise.then(null, function(response) {
              fn(response.data, response.status, response.headers);
            });
            return deferred.promise;
          };
          return deferred;
        };
        return $delegate;
      });
    
    });
    

    【讨论】:

      【解决方案2】:

      如果你想改变 Angular 注入的东西的默认行为,你可以使用$provide 服务上的decorator() 方法。

      var myApp = angular.module("myApp", []);
      
      myApp.config(function ($provide) {
        $provide.decorator("$q", function($delegate) {
          // The $delegate argument here refers to the $q service.
      
          $delegate.defer = function() {
            alert("You just tried to call defer()!");
          };
      
          // Now, every time angular provides an instance of $q via
          // injection, it will return your customized version of $q.
      
          return $delegate;
        });
      });
      

      http://plnkr.co/edit/RuZF2cGkVHwlu7NIhxEZ?p=preview查看上面的例子

      至于修改$q添加成功和错误功能,我目前不确定。但我很确定这就是你想要做的地方。

      【讨论】:

        【解决方案3】:

        恕我直言,@jessegavin 对 $q 的装饰并不完美,它不应该在 success&error 函数中返回 origin 承诺。它会失去扁平化回调金字塔的特性。

        并且它不能将响应数据拆分为成功和错误函数 $httpPromise 剂量。

        例如

        //can't do this..
        somePromise.success(function(){
          return $http.get(...)//another primise
        }).success(function(data){
          //data from $http.get..
        })
        

        这是我的版本,它会识别 http 响应并返回下一个承诺。 让你自己的 $q 具有与 $httpPromise 相同的行为

        $provide.decorator('$q', function($delegate) {
          function httpResponseWrapper(fn) {
            return function(res) {
              if (res.hasOwnProperty('data') && res.hasOwnProperty('status') && res.hasOwnProperty('headers') && res.hasOwnProperty('config') && res.hasOwnProperty('statusText')) {
                return fn(res.data, res.status, res.headers, res.config, res.statusText);
              } else {
                return fn(res);
              }
            };
          };
          function decorator(promise) {
            promise.success = function(fn) {
              return decorator(promise.then(httpResponseWrapper(fn)));
            };
            promise.error = function(fn) {
              return decorator(promise.then(null, httpResponseWrapper(fn)));
            };
            return promise;
          };
          var defer = $delegate.defer;
          $delegate.defer = function() {
            var deferred = defer();
            decorator(deferred.promise);
            return deferred;
          };
          return $delegate;
        });
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-31
        • 2016-03-18
        • 2013-09-11
        • 1970-01-01
        • 2016-09-22
        • 1970-01-01
        • 1970-01-01
        • 2016-04-24
        相关资源
        最近更新 更多