@bornkiller
2015-12-20T08:53:37.000000Z
字数 1649
阅读 2370
angularjs
众所周知,promise只会完成一次状态转换,即不会从resolve状态变为reject状态,通过then函数来执行变相回调。在之前的应用中,自以为是的认为同一个promise只能调用一次then方法,偶然才发现单个promise可以多次利用,实为惭愧。测试代码如下:
var defer = $q.defer(), promise = defer.promise;promise.then(function(message) {console.log(message);return promise;}).then(function(message) {console.log(message);return promise;}).then(function(message) {console.log(message);});$timeout(function() {defer.resolve('hello world');}, 200);
在then方法回调函数内部,如果throw error, then方法则返回reject状态的promise,如果为普通值或无返回值,猜测then方法会返回通过$q.when类似方法包装为promise,如果直接return promise,则then方法直接返回该promise。测试代码中,return 皆为同一个promise,可以多次通过then方法调用,类似于一次包装,多次分发,这是包装`$q``服务的前提。
之前需求中需要多次传递highcharts点击事件,由于highchart-ng封装没有提供对应的传递方式,所有配置项通过service完成,controller中不适宜直接绑定回调,然后通过$scope.$apply方式来刷新视图,所以想到通过promise的多次notify方式来实现,如果不做处理,会出现极其丑陋的代码如下:
// 实际使用方式promise.then(angular.noop, angular.noop, callback);// 预期使用方式promise.notify(callback);
十分不雅。所以可通过包装$q服务的方式来实现,实现如下:
$provide.decorator('$q', function($delegate) {var defer = $delegate.defer;$delegate.defer = function() {var deferred = defer();deferred.promise.notify = function(callback) {deferred.promise.then(angular.noop, angular.noop, callback);return deferred.promise;};return deferred;};return $delegate;})
测试效果代码如下:
var defer = $q.defer(), promise = defer.promise;promise.notify(function(message) {console.log(message);}).then(function(resp) {console.log(resp);}).catch(function(errorDesc) {console.log(errorDesc);});$interval(function() {defer.notify('hello world');}, 200, 10);$timeout(function() {defer.resolve('war never change');}, 2200);
代码输出10次hello world,然后正常输出war never change,表现正常,封装成功。
$http服务也是基于$q服务封装而来,success,error方法封装方式高度类似,不作赘述。