如何使用 .success 和 .error 在 Angularjs 中扩展 $q 承诺
Posted
技术标签:
【中文标题】如何使用 .success 和 .error 在 Angularjs 中扩展 $q 承诺【英文标题】:How can I extend $q promise in Angularjs with a .success and .error 【发布时间】: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;
);
【问题讨论】:
【参考方案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;
);
【讨论】:
也许我的心理 JS 引擎出现了故障,但在我看来,这与HttpPromise
的行为不同。 HttpPromise
should return the original promise,这将返回一个允许链接的新承诺。以上是关于如何使用 .success 和 .error 在 Angularjs 中扩展 $q 承诺的主要内容,如果未能解决你的问题,请参考以下文章
在 AngularJS 中使用带有 Promises 的 success/error/finally/catch
$.ajax()中的success和error的使用注意事项
ThinkPHP3.2.2自定义success及error跳转页面