这篇文章内容主要来自一篇stack Overflow高票答案
声明:此Promise的完成仅仅是为了加深本人对其的明白,和A+范例有些相差,然则的确是如今看过一切promise代码中最美丽,思绪比较清楚的一个。
文章不会特地协助读者温习Promise基础操纵。
状况机
Promise实在本质上就是一个状况机,所以起首我们形貌一个静态的状况机,就像下边如许
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise() {
// 存储的状况是上边的三个:实行中,已完成,已谢绝
var state = PENDING;
// 存储异步效果或许异步毛病音讯
var value = null;
// 负责处置惩罚半途到场的处置惩罚函数
var handlers = [];
}
状况转变
完成了基础的状况机定义,接下来的题目就是完成“状况转变”这个行动的完成:
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise() {
// 存储三个状况
var state = PENDING;
// 一旦涌现状况的转变,异步效果就会被存到这个处所
var value = null;
// 存储胜利或许失利的handler
var handlers = [];
//状况转移到胜利
function fulfill(result) {
state = FULFILLED;
value = result;
}
//状况转移到失利
function reject(error) {
state = REJECTED;
value = error;
}
}
到如今为止,我们给出了两个很地道的变化行动,在开辟的过程当中这两个行动会很不好用,所以我们在这两个行动的基础上构建一个高层次的行动(实在就是加点推断然后封装一层),就像下边这儿,名字就叫做resolve,然则注重和我们一般运用promise挪用的谁人resolve并不一样,不要搞混:
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise() {
var state = PENDING;
var value = null;
var handlers = [];
function fulfill(result) {
state = FULFILLED;
value = result;
}
function reject(error) {
state = REJECTED;
value = error;
}
//这里临时缺乏两个主要函数getThen和doResolve这两个函数,稍后会说道
function resolve(result) {
try {
var then = getThen(result);
//推断then是不是是一个Promise对象
if (then) {
doResolve(then.bind(result), resolve, reject)
return
}
fulfill(result);
} catch (e) {
reject(e);
}
}
}
是的,我们的用到了两个辅佐函数getThen和doResolve,如今给出完成:
/**
* 这里会推断value的范例,我们只需promise.then这个函数,其他的一切返回null
*
* @param {Promise|Any} value
* @return {Function|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;
}
/**
* 这个函数的主要作用就是串主逻辑,完成“变化状况”这个行动
*
* @param {Function} fn A resolver function that may not be trusted
* @param {Function} onFulfilled
* @param {Function} onRejected
*/
function doResolve(fn, onFulfilled, onRejected) {
//done的作用是让onFulfilled或许onRejected仅仅被挪用一次,状况机状况一旦转变没法转头
var done = false;
try {
//在我们一般运用Promise的时刻调的resolve,实在用的就是这里fn注入函数然后挪用
fn(function (value) {
if (done) return
done = true
**onFulfilled(value)**
}, function (reason) {
if (done) return
done = true
onRejected(reason)
})
} catch (ex) {
if (done) return
done = true
onRejected(ex)
}
}
构建
好了,一个完全的状况机已完成,我们完成了一个基础的状况变化逻辑,接下来要做的就是一步一步的朝promise规范进发,这个promise缺乏什么呢,临时缺的就是初始的行动啦(new promise(func)对象一旦被初始化内部代码马上实行),所以我们加上初始行动的开启
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise(fn) {
var state = PENDING;
var value = null;
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实在就是你写的代码
doResolve(fn, resolve, reject);
}
联动
我们完成了状况机,然则如今的题目是我们只能眼睁睁的看着代码的活动直到一个Promise完毕为止,即没法增加也没法猎取效果,这就有很大的局限性了,所以我们要运用then要领来串连Promise,用done要领来完成效果的网络,起首完成done要领,由于then实在说白了就是网络上边的效果–完成本身的逻辑–把效果传递给下一个Promise,做的事变是done的超集。
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise(fn) {
var state = PENDING;
var value = null;
var handlers = [];
function fulfill(result) {
state = FULFILLED;
value = result;
//特地封装一个handle函数处置惩罚后续逻辑,鄙人面有this.handle(handler)要领
handlers.forEach(handle);
//在状况变成已处置惩罚而且之前到场的handler都被处置惩罚完毕的情况下再到场handler就会报错而且没有卵用
handlers = null;
}
function reject(error) {
state = REJECTED;
value = error;
handlers.forEach(handle);
handlers = null;
}
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);
}
}
}
//注重看下面done要领的完成,里边只要一个异步要领,换句话说就是会马上返回不会发生壅塞,我们以后会在then当中挪用done要领,这里的onFulfilled, onRejected就是用户写的处置惩罚函数,promise异步的特征就是如许来的。
this.done = function (onFulfilled, onRejected) {
// ensure we are always asynchronous
setTimeout(function () {
handle({
onFulfilled: onFulfilled,
onRejected: onRejected
});
}, 0);
}
doResolve(fn, resolve, reject);
}
末了,我们来完成Promise.then,完成状况机的串连:
//这段代码有点绕,主要须要完成的事情实在就是,推断上一个Promise是不是完成,然后实行用户的then里边的回调代码,并终究返回一个新的Promise,然后顺次轮回。。。
this.then = function (onFulfilled, onRejected) {
//开启then以后就会返回一个新的promise,然则这个时刻我们还可能有上一个Promise的使命没有完成,所以先把上边一个promise对象的this指向保留下来
var self = this;
//返回一个新包装Promise,这和我们一般的在外边写new Promise是一个原理
return new Promise(function (resolve, reject) {
//done的代码同样是马上返回,然后异步实行的
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);
}
});
});
}
Over
更多参考请看下面:
简朴的完成Promsie
高性能完成Promise,以及特地的wiki