[关闭]
@bornkiller 2015-12-20T16:53:37.000000Z 字数 1649 阅读 2140

angular $q service扩展

angularjs


Promise特性须知

众所周知,promise只会完成一次状态转换,即不会从resolve状态变为reject状态,通过then函数来执行变相回调。在之前的应用中,自以为是的认为同一个promise只能调用一次then方法,偶然才发现单个promise可以多次利用,实为惭愧。测试代码如下:

  1. var defer = $q.defer()
  2. , promise = defer.promise;
  3. promise.then(function(message) {
  4. console.log(message);
  5. return promise;
  6. }).then(function(message) {
  7. console.log(message);
  8. return promise;
  9. }).then(function(message) {
  10. console.log(message);
  11. });
  12. $timeout(function() {
  13. defer.resolve('hello world');
  14. }, 200);

then方法回调函数内部,如果throw errorthen方法则返回reject状态的promise,如果为普通值或无返回值,猜测then方法会返回通过$q.when类似方法包装为promise,如果直接return promise,则then方法直接返回该promise。测试代码中,return 皆为同一个promise,可以多次通过then方法调用,类似于一次包装,多次分发,这是包装`$q``服务的前提。

包装$q服务支持notify快捷方式

之前需求中需要多次传递highcharts点击事件,由于highchart-ng封装没有提供对应的传递方式,所有配置项通过service完成,controller中不适宜直接绑定回调,然后通过$scope.$apply方式来刷新视图,所以想到通过promise的多次notify方式来实现,如果不做处理,会出现极其丑陋的代码如下:

  1. // 实际使用方式
  2. promise.then(angular.noop, angular.noop, callback);
  3. // 预期使用方式
  4. promise.notify(callback);

十分不雅。所以可通过包装$q服务的方式来实现,实现如下:

  1. $provide.decorator('$q', function($delegate) {
  2. var defer = $delegate.defer;
  3. $delegate.defer = function() {
  4. var deferred = defer();
  5. deferred.promise.notify = function(callback) {
  6. deferred.promise.then(angular.noop, angular.noop, callback);
  7. return deferred.promise;
  8. };
  9. return deferred;
  10. };
  11. return $delegate;
  12. })

测试效果代码如下:

  1. var defer = $q.defer()
  2. , promise = defer.promise;
  3. promise.notify(function(message) {
  4. console.log(message);
  5. }).then(function(resp) {
  6. console.log(resp);
  7. }).catch(function(errorDesc) {
  8. console.log(errorDesc);
  9. });
  10. $interval(function() {
  11. defer.notify('hello world');
  12. }, 200, 10);
  13. $timeout(function() {
  14. defer.resolve('war never change');
  15. }, 2200);

代码输出10次hello world,然后正常输出war never change,表现正常,封装成功。

后记

$http服务也是基于$q服务封装而来,successerror方法封装方式高度类似,不作赘述。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注