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', [])
.controller('testController', function ($scope, $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, onRejected, 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', function ($scope, $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);
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。