最近买了掘金小册,里面有关于promise的实现。看了半天,终于理解简单的promise。并且我相信工做中也不会说让你完整实现一个。因此我在理解原理以后,我就再也不深刻了。前端
这里主要是Promise/A+ 规范,可是从简单promise上去理解,实际上咱们须要知道的是三个状态面试
const pending = 'pending'; //等待
const resolved = 'resolved'; //成功
const rejected = 'rejected'; //失败复制代码
很简单的三个状态。数组
我在没有实现函数以前是这样想的。promise
一、自己是链式调用bash
二、链式调用和回调函数相似函数
核心在于和回调函数相似。promise实际上也是相似的操做方式。ui
回顾下回调函数:回调函数是在当你的操做或者结果须要到达这个执行结果的时候你把函数看成参数的形式执行,而后能够获得结果。this
说白了就是在恰达的时机去执行你的函数。spa
这里来一个简单的回调函数。看看prototype
function huidiao(a, callback) {
callback(a * 10);
}
huidiao(20, e => {
console.log(e);
});复制代码
function MyPromise(fn) {
const that = this;
that.state = pending;
that.value = null;
that.resolvedCallbacks = [];
that.rejectedCallbacks = [];
//成功的回调函数
// 失败的回调函数
}复制代码
这里this不须要我解释吧。
value是到时候的执行结果
下面两个为何是数组呢?这里确定有人会疑问,我提早说一下,这里是放成功执行函数和失败执行函数的。
//成功的回调函数
function resolve(value) {
if(that.state === pending) {
that.state = resolved;
that.value = value;
that.resolvedCallbacks.map(cb => cb(that.value));
}
}
// 失败的回调函数
function reject(value) {
if(that.state === pending) {
that.state = rejected;
that.value = value;
that.rejectedCallbacks.map(cb => cb(that.value));
}
}复制代码
这里能看到会有传入值,还有是执行函数,和改变状态。
改变状态和给值没必要多说,至于为何是对数组进行map而后执行是由于后面会存放进来函数,函数须要执行。
埋个坑。后面解释
try {
fn(resolve, reject)
} catch (e) {
reject(e);
}复制代码
MyPromise.prototype.then = function (onFulfilled, onRejected) {
const that = this;
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r };
if (that.state === pending) {
that.resolvedCallbacks.push(onFulfilled);
that.rejectedCallbacks.push(onRejected);
}
if (that.state === resolved) {
onFulfilled(that.value);
}
if (that.state === rejected) {
onRejected(that.value);
}
};复制代码
这里onFulfilled, onRejected是规范里面的命名方式,判断是不是函数是为了阻止非回调函数的执行
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 0)
}).then((value) => {
console.log(value)
});复制代码
结果是正常输出1
看了上面一堆代码是否是不理解,也感受懵逼呢?
这里我来说一下执行顺序,你们就理解了。
一、根据链式调用顺序,先会执行then的方法。这时候是确定是会执行到pending状态,那么就会把
(value) => {
console.log(value)
}复制代码
传入resolvedCallbacks给进入数组当中
二、函数解析的时候是会把预先定义好的变量等都完成,函数也会提早解析好,关键是在这里会执行回调函数
try {
fn(resolve, reject)
} catch (e) {
reject(e);
}复制代码
上文中
setTimeout(() => {
resolve(1)
}, 0)复制代码
是被fn()函数执行了。注意是经过resolve执行传入结果。这里自己是回调函数的概念。
二、resolve函数获得结果,判断以后发现当前状态是等待状态那么就会执行对应的结果
三、最后经过链式调用的回调方式来获得结果
四、至于为何是数组或者这么多状态,那是由于咱们还有catch方法。若是直接就执行了,那么就结果不对了。
代码自己根据《前端面试之道》小册来编写。
推广下个人摸鱼群:797957786