更好地理解 Promise
状态机
由于 promise 只是一个状态机,我们应该首先引入我们后面需要的状态信息。
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise() {
// 状态可以是 PENDING, FULFILLED or REJECTED
let state = PENDING;
// 在状态变为 FULFILLED or REJECTED 后,存储 value 或者 error
let value = null;
// 通过调用 .then 或者 .done,存储成功或失败的 handlers
var handlers = [];
}
状态转变
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise() {
// 状态可以是 PENDING, FULFILLED or REJECTED
let state = PENDING;
// 在状态变为 FULFILLED or REJECTED 后,存储 value 或者 error
let value = null;
// 通过调用 .then 或者 .done,存储成功或失败的 handlers
var handlers = [];
function fulfill(result) {
state = FULFILLED;
value = result;
}
function reject(error) {
state = REJECTED;
value = error;
}
}
这为我们提供了基本的低级转换,但让我们考虑一个额外的、更高级别的转换,resolve
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise() {
// store state which can be PENDING, FULFILLED or REJECTED
var state = PENDING;
// store value once FULFILLED or REJECTED
var value = null;
// store sucess & failure handlers
var handlers = [];
function fulfill(result) {
state = FULFILLED;
value = result;
}
function reject(error) {
state = REJECTED;
value = error;
}
function resolve(result) {
try {
let then = getThen(result);
if (then) {
doResolve(then.bind(result), resolve, reject)
return
}
// then 是 null 时调用 fulfill,即 result 是纯值时调用
fulfill(result);
} catch (e) {
reject(e);
}
}
}
注意,resolve 函数接收一个 promise 对象或者其他非 promise 对象。接收 promise 对象时,会等待此对象完成状态转换。
一个 promise 是不能通过另一个 promise 完成状态转换到 fulfilled,此时我们将暴露的是这个 resolve 函数,而不是内部的 fulfill 函数,我们使用了辅助方法:
- getThen 方法
/** * 检查 value 是否是 Promise ,如果是, 返回 value.then. * * @param Promise 或其他任何值 * @return 函数或者 null */ function getThen(value) { var t = typeof value; if (value && (t === 'object' || t === 'function')) { var then = value.then; if (typeof then === 'function') { return then; } } return null; }
- doResolve 方法
/** * 接收一个潜在的错误行为的 resolver 函数,并确保 onFulfilled 和 onRejected 只会被调用一次 * * 此方法没有异步安全性 * * @param {Function} fn : 一个 resolver 函数,可能不可信的 * @param {Function} 函数 onFulfilled * @param {Function} 函数 onRejected */ function doResolve(fn, onFulfilled, onRejected) { var done = false; try { fn(function (value) { if (done) return done = true onFulfilled(value) }, function (reason) { if (done) return done = true onRejected(reason) }) // fn 函数执行结束 } catch (ex) { if (done) return done = true onRejected(ex) } }
搭建 Promise
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise(fn) {
// store state which can be PENDING, FULFILLED or REJECTED
var state = PENDING;
// store value once FULFILLED or REJECTED
var value = null;
// store sucess & failure handlers
var handlers = [];
function fulfill(result) {
state = FULFILLED;
value = result;
}
function reject(error) {
state = REJECTED;
value = error;
}
function resolve(result) {
try {
var then = getThen(result);
if (then) {
doResolve(then.bind(result), resolve, reject)
return
}
fulfill(result);
} catch (e) {
reject(e);
}
}
doResolve(fn, resolve, reject);
}
我们多次使用 doResolve
,因为我们有多个不可信任的 resolver。fn
被允许多次调用 resolve
和 reject
,即使抛出了异常。我们有责任确保承诺只变为 resolved 或 rejected 一次,然后永远不会再转换到不同的状态。
观察
状态机已经完整了,但是我们不能观察或者改变状态机,我们的究极目标是实现 .then
方法,但是这里先实现一个比 .then
简单地 .done
方法。
此 .done(onFulfilled, onRejected)
方法:
- 只会被
onFulfilled
或者onRejected
调用 - 只会被调用一次
- 直到下一个滴答声(即在
.done
方法返回之后)才会被调用 - 无论 rpomsie 在我们调用
.done
之前还是之后 resolved 了,.done
都会被调用
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise(fn) {
// store state which can be PENDING, FULFILLED or REJECTED
var state = PENDING;
// store value once FULFILLED or REJECTED
var value = null;
// store sucess & failure handlers
var handlers = [];
function fulfill(result) {
state = FULFILLED;
value = result;
}
function reject(error) {
state = REJECTED;
value = error;
}
function resolve(result) {
try {
var then = getThen(result);
if (then) {
doResolve(then.bind(result), resolve, reject)
return
}
fulfill(result);
} catch (e) {
reject(e);
}
}
function handle(handler) {
if (state === PENDING) {
handlers.push(handler);
} else {
if (state === FULFILLED &&
typeof handler.onFulfilled === 'function') {
handler.onFulfilled(value);
}
if (state === REJECTED &&
typeof handler.onRejected === 'function') {
handler.onRejected(value);
}
}
}
this.done = function (onFulfilled, onRejected) {
// ensure we are always asynchronous
setTimeout(function () {
handle({
onFulfilled: onFulfilled,
onRejected: onRejected
});
}, 0);
}
doResolve(fn, resolve, reject);
}
实现. then
then 需要返回一个 Promise 对象
this.then = function (onFulfilled, onRejected) {
var self = this;
return new Promise(function (resolve, reject) {
return self.done(function (result) {
if (typeof onFulfilled === 'function') {
try {
return resolve(onFulfilled(result));
} catch (ex) {
return reject(ex);
}
} else {
return resolve(result);
}
}, function (error) {
if (typeof onRejected === 'function') {
try {
return resolve(onRejected(error));
} catch (ex) {
return reject(ex);
}
} else {
return reject(error);
}
});
});
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。