在上一篇文章里面,我们实现了一个简单的Promise
,已可以满足一些较简单的场景。但却无法进行then的Promise链式衔接,比如这样:
getUserId()
.then(getUserInfoById)
.then(function (info) {
});
function getUserJobById(id) {
return new Promise(function (resolve) {
fetch(baseUrl + id, function(res) {
resolve(res);
});
});
}
这种场景相信用过promise
的人都知道会有很多,那么类似这种就是所谓的链式Promise
。
链式Promise是指在当前promise达到fulfilled
状态后,即开始进行下一个promise(后邻promise)。那么我们如何衔接当前promise和后邻promise呢?(这是这里的难点)。
只需在then方法里面return一个promise就好啦。可见Promises/A+规范中的2.2.7
Promise/A+规范
then
must return a promise [3.3].
function RPromise(fn) {
var state = 'pending',
value = null,
callbacks = []; //callbacks为数组,因为可能同时有很多个回调
this.then = function (onFulfilled) {
return new RPromise(function (resolve) {
handle({
onFulfilled: onFulfilled || null,
resolve: resolve
});
});
};
// this.then = function (onFulfilled) {
// if (state === 'pending') {
// callbacks.push(onFulfilled);
// //ask 为什么要return this?
// return this;
// }
// //假如state已经切换至其他状态,直接执行回调
// setTimeout(function () {
// onFulfilled(value);
// }, 0);
//
// return this;
// };
// 关键tip-2
// 1: 链式promise之间有一个桥梁promise,可称之为bridge promise,用于衔接两个promise,包装在then函数中
// 2: 当前一个promise resolve之后,bridge promise负责传递之前promise的值
// 3: 将当前promise的值和bridge promise的resolve方法传给下一个promise之后,在下一个promise resolve的时候,执行bridge promise的resolve方法,再执行本身后注册的then函数中的promise resolve
// 4: 执行完四个promise(promise 1 - getUserId, promise 2 - getUserId bridge, promise 3 - getUserInfoById, promise 4 - getUserInfoById bridge)之后,继续执行后面的then函数
function handle(callback) {
if (state === 'pending') {
callbacks.push(callback);
return;
}
//如果then中没有传递任何东西
if (!callback.onFulfilled) {
callback.resolve(value);
return;
}
var ret = callback.onFulfilled(value);
callback.resolve(ret);
}
function resolve(newValue) {
state = 'fulfilled';
value = newValue;
// Promises/A+规范明确要求回调需要通过异步方式执行,用以保证一致可靠的执行顺序
// 保证then函数的回调都已注册完毕
// 比如promise内部的函数是同步函数
// function getUserId() {
// return new Promise(function (resolve) {
// resolve(9876);
// });
// }
// getUserId().then(function (id) {
// // 一些处理
// });
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then;
if (typeof then === 'function') {
then.call(newValue, resolve);
return;
}
}
state = 'fulfilled';
value = newValue;
// console.log('value' + value);
setTimeout(function () {
callbacks.forEach(function (callback) {
handle(callback);
});
}, 0);
}
fn(resolve);
}
//eg:
var testAsyncFunc1 = function () {
return new RPromise(function (resolve) {
// resolve(123);
setTimeout(function () {
resolve(123)
}, 100)
})
};
var testAsyncFunc2 = function (res) {
return new RPromise(function (resolve) {
setTimeout(function () {
resolve(res + 456)
}, 100);
})
};
testAsyncFunc1()
.then(testAsyncFunc2)
.then(function (res) {
console.log(res);
});
console.log(456);
1.then方法中,创建并返回了新的Promise实例,这是串行Promise的基础,并且支持链式调用。
2.handle方法是promise内部的方法。then方法传入的形参onFulfilled以及创建新Promise实例时传入的resolve均被push到当前promise的callbacks队列中,这是衔接当前promise和后邻promise的关键所在(这里一定要好好的分析下handle的作用)。
3.testAsyncFunc1生成的promise(简称testPromise1)异步操作成功,执行其内部方法resolve,传入的参数正是异步操作的结果123
4.调用handle方法处理callbacks队列中的回调:testAsyncFunc2 方法,生成新的promise(testAsyncFunc2 promise)
5.执行之前由testAsyncFunc1 promise的then方法生成的新promise(称为bridge promise)的resolve方法,传入参数为testAsyncFunc1 promise。这种情况下,会将该resolve方法传入testAsyncFunc2 promise的then方法中,并直接返回。
6/在testAsyncFunc2 promise异步操作成功时,执行其callbacks中的回调:testAsyncFunc1 bridge promise中的resolve方法
7.最后执行testAsyncFunc1 bridge promise的后邻promise的callbacks中的回调。
// 关键tip-2
1: 链式promise
之间有一个桥梁promise
,可称之为bridge promise
,用于衔接两个promise
,包装在then
函数中 2: 当前一个promise resolve
之后,bridge promise
负责传递之前promise
的值
3: 将当前promise
的值和bridge promise
的resolve
方法传给下一个promise
之后,在下一个promise resolve
的时候,执行bridge promise
的resolve
方法,再执行本身后注册的then
函数中的promise resolve
4: 执行完四个promise(promise 1 - getUserId, promise 2 - getUserId bridge, promise 3 - getUserInfoById, promise 4 - getUserInfoById bridge)
之后,继续执行后面的then
函数
网友评论