原文https://zhuanlan.zhihu.com/p/26815654
Promise实现
Promise是什么,怎么样使用就介绍到此,另外一个问题是面试过程中经常也会被提及的:如何实现一个Promise,当然,限于篇幅,我们这里只讲思路,不会长篇大论。
构造函数
首先创建一个构造函数,供实例化创建promise,该构造函数接受一个函数参数,实例化时,会立即调用该函数,然后返回一个Promise对象:
var MyPromise = (() => {
var value = undefined; // 当前Promise
var tasks = []; // 完成回调队列
var rejectTasks = []; // 拒绝回调队列
var state = 'pending'; // Promise初始为等待态
// 辅助函数,使异步回调下一轮事件循环执行
var nextTick = (callback) => {
setTimeout(callback, 0);
};
// 辅助函数,传递Promsie的状态值
var ref = (value) => {
if (value && typeof value.then === 'function') {
// 若状态值为thenable对象或Promise,直接返回
return value;
}
// 否则,将最终值传递给下一个then方法注册的回调函数
return {
then: function(callback) {
return ref(callback(value));
}
}
};
var resolve = (val) => {};
var reject = (reason) => {};
function MyPromise(func) {
func(resolve.bind(this), reject.bind(this));
}
return MyPromise;
});
静态方法
在实例化创建Promise时,我们会将构造函数的两个静态方法:resolve和reject传入初始函数,接下来需要实现这两个函数:
var resolve = (val) => {
if (tasks) {
value = ref(val);
state = 'resolved'; // 将状态标记为已完成
// 依次执行任务回调
tasks.forEach((task) => {
value = nextTick((val) => {task0;});
});
tasks = undefined; // 决议后状态不可变
return this;
}
};
var reject = (reason) => {
if (tasks) {
value = ref(reason);
state = 'rejected'; // 将状态标记为已完成
// 依次执行任务回调
tasks.forEach((task) => {
nextTick((reason) => {task[1](value);});
});
tasks = undefined; // 决议后状态不可变
return this;
}
};
还有另外两个静态方法,原理还是一样,就不细说了。
实例方法
目前构造函数,和静态方法完成和拒绝Promise都已经实现,接下来需要考虑的是Promise的实例方法和链式调用:
MyPromise.prototype.then = (onFulfilled, onRejected) => {
onFulfilled = onFulfilled || function(value) {
// 默认的完成回调
return value;
};
onRejected = onRejected || function(reason) {
// 默认的拒绝回调
return reject(reason);
};
if (tasks) {
// 未决议时加入队列
tasks.push(onFulfilled);
rejectTasks.push(onRejected);
} else {
// 已决议,直接加入事件循环执行
nextTick(() => {
if (state === 'resolved') {
value.then(onFulfilled);
} else if (state === 'rejected') {
value.then(onRejected);
}
});
}
return this;
};
实例
以上可以简单实现Promise部分异步管理功能:
var promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('完成');
}, 0);
});
promise.then((msg) => {console.log(msg);});
本篇由回调函数起,介绍了回调处理异步任务的常见问题,然后介绍Promises/A+规范及Promise使用,最后就Promise实现做了简单阐述(之后有机会会详细实现一个Promise),花费一周终于把基本知识点介绍完,下一篇将介绍JavaScript异步与生成器实现。
网友评论