promise是什么
这里不解释promise是什么,因为我相信你来看文章的时候已经知道你什么是promise了。
此处有promise规范。
Promise/A+规范 中文
Promise/A+
ES2016:MDN Promise
$q
$q是AngularJS提供的一个服务。
$q是跟AngularJS的$rootScope模板集成的,所以在AngularJS中执行和拒绝都很快。(编辑器疯了,dollar符号就是打不出来,就叫 'dollar'q)
$q是跟AngularJS模板引擎集成的,这意味着在视图中找到任何Promise都会在视图中被执行或者拒绝。
如何在AngularJS中使用
直接上栗子,程序员都不喜欢听你废话~〒▽〒
var app = angular.module('app',[]) .controller('testController',function ($scope,$q) { //定义一个defer var defer = $q.defer(); var promise = defer.promise; promise.then(function (data) { //成功后的逻辑处理 },function (error) { //失败后的逻辑处理 }); //模拟通过--实际应该是一个异步的callback中调用 defer.resolve('[data]'); //模拟拒绝--实际应该是一个异步的callback中调用 defer.reject('[data]'); });
链式调用
then会返回一个新的promise对象,所以直接jQuery风格的链式调用。
还是直接上栗子:
var app = angular.module('app',$q) { //定义一个defer var defer = $q.defer(); var promise = defer.promise; promise.then(function () { console.log('then-resolved-1'); },function () { console.log('then-rejected-1'); }) .then(function () { console.log('then-resolved-2'); },function () { console.log('then-rejected-2'); }); //模拟通过--实际应该是一个异步的callback中调用 defer.resolve('[data]'); //模拟拒绝--实际应该是一个异步的callback中调用 defer.reject('[data]'); });
来看下是如何实现链式调用的,下面是AngularJS源码实现:
//angular.js Promise.prototype = { then: function(onFulfilled,onRejected,progressBack) { var result = new Deferred();//此处可以看出,每个then都会返回一个新的Deferred对象。 this.$$state.pending = this.$$state.pending || []; this.$$state.pending.push([result,onFulfilled,progressBack]); if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); return result.promise; },//其他省略 ... } //Deferred定义 function Deferred() { this.promise = new Promise();//可以看到defer的promise对象是一个new Promise() //Necessary to support unbound execution :/ this.resolve = simpleBind(this,this.resolve); this.reject = simpleBind(this,this.reject); this.notify = simpleBind(this,this.notify); }
链式调用参数传递
看过上面链式调用的栗子和AngularJS的源码后,大家就能知道每个then的上下文其实是不一样的,因为每次都是新new 出来的Promise对象。
先给栗子:
var app = angular.module('app',[]) .controller('testController',$q) { //定义一个defer var defer = $q.defer(); var promise = defer.promise; promise.then(function (data) { //... return data;// data = 1 },function (error) { //... }) .then(function (data) { //... return data;//data = 1 },function (error) { //... }); //模拟通过--实际应该是一个异步的callback中调用 defer.resolve('1'); });
接下来看一段源码解析,看看AngularJS是如何调用Promise的。
//angular.js Deferred.prototype = { resolve: function(val) { if (this.promise.$$state.status) return; if (val === this.promise) { this.$$reject($qMinErr( 'qcycle',"Expected promise to be resolved with value other than itself '{0}'",val)); } else { this.$$resolve(val);//实际调用这个方法 } },$$resolve: function(val) { var then,fns; fns = callOnce(this,this.$$resolve,this.$$reject); try { if ((isObject(val) || isFunction(val))) then = val && val.then; if (isFunction(then)) { this.promise.$$state.status = -1; then.call(val,fns[0],fns[1],this.notify); } else { this.promise.$$state.value = val; this.promise.$$state.status = 1; scheduleProcessQueue(this.promise.$$state);//最终在此处加入到队列中 } } catch (e) { fns[1](e); exceptionHandler(e); } },... //scheduleProcessQueue定义 function scheduleProcessQueue(state) { if (state.processScheduled || !state.pending) return; state.processScheduled = true; nextTick(function() { processQueue(state); });//此处调用进入processQueue } function processQueue(state) { var fn,promise,pending; pending = state.pending; state.processScheduled = false; state.pending = undefined; for (var i = 0,ii = pending.length; i < ii; ++i) { promise = pending[i][0]; fn = pending[i][state.status]; try { if (isFunction(fn)) { promise.resolve(fn(state.value));//此处是链式调用传参关键,fn(state.value)实际是上一个then的resolve的返回值,所以能知道,如果需要所有的then都能取到异步任务的返回值,就得在then的resolve函数中,将值返回。 } else if (state.status === 1) { promise.resolve(state.value); } else { promise.reject(state.value); } } catch (e) { promise.reject(e); exceptionHandler(e); } } }