在手写Promise之前,我们首先要理一下Promise的基本结构
基本结构
1.Promise是一个类, 在执行这个类的时候 需要传递一个执行器进去,执行器会立即执行
2.Promise 中有三个状态 分别是 成功(fulfilled)、失败(rejected)和等待(pending)
pending -> fulfilled
pending -> rejected
状态一旦确定就不可更改
3.resolve和reject函数是用来更改状态的
resolve: fulfilled
reject: rejected
4. then方法内部做的就是判断状态,如果是成功状态,调用成功回调函数,如果是失败状态,调用失败回调函数
5. then方法有两个回调,一个是成功回调,回调参数表示成功之后的值,一个是失败回调,回调参数表示失败的原因
明确了这些我们继续往下写
基本结构理清了我们先搭好架子
class MyPromise {
constructor(executor) {
// 执行传入的函数参数
executor(this.resolve, this.reject)
}
// 更改为成功状态
resolve = () => {
}
// 更改为失败状态
reject = () => {
}
}
module.exports = MyPromise;
增加状态
增加一个变量status
记录当前实例状态,三种状态pending、fulfilled、rejected
,初始值是pending
,在Promise中,状态一旦确定是不可更改的,所以在更改状态前要先进行判断状态是否是等待状态。
加入的代码
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 执行传入的函数参数
executor(this.resolve, this.reject)
}
status = PENDING;
// 更改为成功状态
resolve = () => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
}
// 更改为失败状态
reject = () => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
}
}
module.exports = MyPromise;
加入then方法
then方法内部做的就是判断状态,如果是成功状态,调用成功回调函数,如果是失败状态,调用失败回调函数。
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 执行传入的函数参数
executor(this.resolve, this.reject)
}
status = PENDING;
// 更改为成功状态
resolve = () => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
}
// 更改为失败状态
reject = () => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
}
then(successCallback, failCallback) {
// 判断状态
if (this.status === FULFILLED) {
successCallback()
} else if (this.status === REJECTED) {
failCallback()
}
}
}
module.exports = MyPromise;
then方法的回调参数
then有两个回调,一个是成功回调,回调参数表示成功之后的值,一个是失败回调,回调参数表示失败的原因,回调的参数是们调用成功回调或者失败回调所传入的值,所以这个值我们要要在resolve和reject中记录下来。
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 执行传入的函数参数
executor(this.resolve, this.reject)
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
}
then(successCallback, failCallback) {
// 判断状态
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECTED) {
failCallback(this.reason)
}
}
}
module.exports = MyPromise;
现在我们已经完成了一个最简单的Promise了,但是我们现在的代码没有考虑到异步的情况,接下来我们要给Promise中加入异步逻辑
给Promise加入异步逻辑
异步代码是会进入等待的,我们then方法要处理等待这种情况
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 执行传入的函数参数
executor(this.resolve, this.reject)
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = undefined;
// 失败回调
failCallback = undefined;
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
this.successCallback && this.successCallback(this.value);
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
this.failCallback && this.failCallback(this.reason);
}
then(successCallback, failCallback) {
// 判断状态
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback = successCallback;
this.failCallback = failCallback;
}
}
}
module.exports = MyPromise;
现在我们是只考虑了只调用一次then方法的异步处理,then方法可以调用多次,有多个回调,我们都要保存下来,所以我们还要改造一下
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 执行传入的函数参数
executor(this.resolve, this.reject)
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
// this.successCallback && this.successCallback(this.value);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.successCallback.length) this.successCallback.shift()(this.value)
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
// this.failCallback && this.failCallback(this.reason);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.failCallback.length) this.failCallback.shift()(this.reason)
}
then(successCallback, failCallback) {
// 判断状态
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
}
}
module.exports = MyPromise;
then方法的链式调用
Promise中的then方法是可以链式调用的,后一个then方法的回调函数拿到的值实际上是上一个then方法的回调函数的返回值
改造一下代码:
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 执行传入的函数参数
executor(this.resolve, this.reject)
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
// this.successCallback && this.successCallback(this.value);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.successCallback.length) this.successCallback.shift()(this.value)
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
// this.failCallback && this.failCallback(this.reason);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.failCallback.length) this.failCallback.shift()(this.reason)
}
then(successCallback, failCallback) {
// 创建一个新的promise对象 并返回
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value)
resolve(x)
} else if (this.status === REJECTED) {
// 将回调的结果传给下一个then方法
failCallback(this.reason)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
});
return promise2
}
}
module.exports = MyPromise;
在链式调用then方法的时候,在then方法的回调函数中,我们既可以返回一个promise对象,也可以返回一个普通值,如果我们返回的是一个普通值的话我们可以通过resolve方法把值传递给下一个promise对象,如果我们返回的是一个promise对象,我们要先查看promise对象的返回结果,如果这个结果是成功的,我们要调用resolve方法把值传递给下一个promise对象,如果这个结果是失败的,我们要调用reject方法把失败的原因传递给下一个promise对象,这个操作在三个状态中都有,所以我们抽出来写一个公共方法
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 执行传入的函数参数
executor(this.resolve, this.reject)
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
// this.successCallback && this.successCallback(this.value);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.successCallback.length) this.successCallback.shift()(this.value)
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
// this.failCallback && this.failCallback(this.reason);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.failCallback.length) this.failCallback.shift()(this.reason)
}
then(successCallback, failCallback) {
// 创建一个新的promise对象 并返回
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value)
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(x, resolve, reject)
} else if (this.status === REJECTED) {
// 将回调的结果传给下一个then方法
failCallback(this.reason)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
});
return promise2
}
}
resolvePromise(x, resolve, reject) {
if (x instanceof MyPromise) {
// 是promise对象
// x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
x.then(resolve, reject)
} else {
// 是普通值 直接返回
resolve(x)
}
}
module.exports = MyPromise;
在then方法的回调函数当中,我们是不能返回当前这个then方法它所返回的promise对象的(有点绕,就是不能自己返回自己,promise的循环调用程序是不被允许的)例如下面这个例子
var promise = new Promise((resolve,reject) {
resolve(100)
});
var p1 = promise.then(value => {
console.log(value)
// 自己返回自己
return p1
})
p1.then(()=>,(reason) => {
//打印报错结果
console.log(reason.message)
})
我们的MyPromise中也要加入这样的逻辑
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 执行传入的函数参数
executor(this.resolve, this.reject)
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
// this.successCallback && this.successCallback(this.value);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.successCallback.length) this.successCallback.shift()(this.value)
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
// this.failCallback && this.failCallback(this.reason);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.failCallback.length) this.failCallback.shift()(this.reason)
}
then(successCallback, failCallback) {
// 创建一个新的promise对象 并返回
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
// 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
setTimeout(() => {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value)
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject)
}, 0)
} else if (this.status === REJECTED) {
// 将回调的结果传给下一个then方法
failCallback(this.reason)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
});
return promise2
}
}
resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
// 自己返回自己 返回reject
reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
// 是promise对象
// x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
x.then(resolve, reject)
} else {
// 是普通值 直接返回
resolve(x)
}
}
module.exports = MyPromise;
捕捉错误及then链式调用其他状态代码补充
当执行器在执行过程当中发生错误的时候,我们就要让promise的状态变成失败的状态,也就是说我们要在then方法的第二个参数中捕获到这个错误,在其他的状态中也要加入这样的处理
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 执行传入的函数参数
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e);
}
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
// this.successCallback && this.successCallback(this.value);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.successCallback.length) this.successCallback.shift()()
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
// this.failCallback && this.failCallback(this.reason);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.failCallback.length) this.failCallback.shift()()
}
then(successCallback, failCallback) {
// 创建一个新的promise对象 并返回
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
// 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
this.failCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
}
});
return promise2
}
}
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
// 自己返回自己 返回reject
reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
// 是promise对象
// x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
x.then(resolve, reject)
} else {
// 是普通值 直接返回
resolve(x)
}
}
module.exports = MyPromise;
将then方法的参数变成可选参数
then方法的两个参数都是可选参数,我们可以选择什么都不传,但是他的状态会一直传递给有回调函数的then
我们改进一下代码:
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 执行传入的函数参数
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e);
}
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
// this.successCallback && this.successCallback(this.value);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.successCallback.length) this.successCallback.shift()()
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
// this.failCallback && this.failCallback(this.reason);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.failCallback.length) this.failCallback.shift()()
}
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason };
// 创建一个新的promise对象 并返回
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
// 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
this.failCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
}
});
return promise2
}
}
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
// 自己返回自己 返回reject
reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
// 是promise对象
// x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
x.then(resolve, reject)
} else {
// 是普通值 直接返回
resolve(x)
}
}
module.exports = MyPromise;
加入Promise.all()方法
Promise.all()方法允许我们按照异步代码调用的顺序得到异步代码执行的结果
Promise.all()方法接收一个数组,这个数组里面的我们可以填入任何值,包括普通值和Promise对象,数组当中值的顺序一定是我们得到的结果的顺序、
Promise.all()方法的返回值也是一个Promise对象,所以我们也可以链式调用then方法
在Promise.all()方法当中所有的Promise对象,如果他的状态都是成功的,那么all()方法它最后的结果就是成功的,如果有一个是失败的,那么它最后的结果就是失败的
all()方法是一个静态方法
代码实现:
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 执行传入的函数参数
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e);
}
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
// this.successCallback && this.successCallback(this.value);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.successCallback.length) this.successCallback.shift()()
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
// this.failCallback && this.failCallback(this.reason);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.failCallback.length) this.failCallback.shift()()
}
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason };
// 创建一个新的promise对象 并返回
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
// 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
this.failCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
}
});
return promise2
}
static all(array) {
let result = [];
// 为了等待异步任务的执行结果 我们定义一个index 当 index和数组的长度相等,说明所有任务都已完成
let index = 0;
return new MyPromise((resolve, reject) => {
const addData = (key, value) => {
result[key] = value;
index++;
if (index === array.length) {
resolve(result);
}
}
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof MyPromise) {
// promise 对象
current.then(value => addData(i, value), reason => reject(reason))
} else {
// 普通值
addData(i, array[i]);
}
}
})
}
}
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
// 自己返回自己 返回reject
reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
// 是promise对象
// x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
x.then(resolve, reject)
} else {
// 是普通值 直接返回
resolve(x)
}
}
module.exports = MyPromise;
实现Promise.resolve()方法
Promise.resolve()方法的作用是将给定的的值转换成Promise对象,它也可以接收一个promise对象,resolve内部会判断你给定的值是普通值还是promise对象
resolve()是一个静态方法
代码实现:
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 执行传入的函数参数
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e);
}
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
// this.successCallback && this.successCallback(this.value);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.successCallback.length) this.successCallback.shift()()
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
// this.failCallback && this.failCallback(this.reason);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.failCallback.length) this.failCallback.shift()()
}
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason };
// 创建一个新的promise对象 并返回
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
// 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
this.failCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
}
});
return promise2
}
static all(array) {
let result = [];
// 为了等待异步任务的执行结果 我们定义一个index 当 index和数组的长度相等,说明所有任务都已完成
let index = 0;
return new MyPromise((resolve, reject) => {
const addData = (key, value) => {
result[key] = value;
index++;
if (index === array.length) {
resolve(result);
}
}
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof MyPromise) {
// promise 对象
current.then(value => addData(i, value), reason => reject(reason))
} else {
// 普通值
addData(i, array[i]);
}
}
})
}
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value))
}
}
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
// 自己返回自己 返回reject
reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
// 是promise对象
// x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
x.then(resolve, reject)
} else {
// 是普通值 直接返回
resolve(x)
}
}
module.exports = MyPromise;
Promise.finally()和Promise.catch()方法实现
无论当前promise的最终状态是成功的还是失败的finally方法当中的回调函数始终都会被执行一次,在finally()方法后面我们可以链式调用then方法拿到当前promise对象最终的返回结果
catch()方法的作用是用来处理当前promise对象最终的状态为失败的情况的,当我们调用then方法是可以不传递失败回调的,如果我们不传递失败回调,那么失败回调就会被catch方法捕获从而去执行传入到catch方法当中的回调函数
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor(executor) {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 执行传入的函数参数
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e);
}
}
// Promise状态
status = PENDING;
// 成功之后的值
value = undefined;
// 失败之后的原因
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
// 更改为成功状态
resolve = value => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在则调用
// this.successCallback && this.successCallback(this.value);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.successCallback.length) this.successCallback.shift()()
}
// 更改为失败状态
reject = reason => {
// 如果不是等待状态 就阻止程序向下执行
if (this.status !== PENDING) return;
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在 如果存在则调用
// this.failCallback && this.failCallback(this.reason);
// 以数组的长度作为条件,将前面的回调函数弹出并调用 shift()方法的返回值就是我们需要的函数
// 每当执行一次数组就会删除一个,数组长度为零时就不再执行
while (this.failCallback.length) this.failCallback.shift()()
}
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason };
// 创建一个新的promise对象 并返回
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
// 由于resolvePromise 中的promise2在new Mypromise没有执行完之前是拿不到的,所以这里我们要加入setTimeout改为异步代码
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
} else {
// 等待状态
// 将成功回调和失败回调保存起来
this.successCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = successCallback(this.value);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
this.failCallback.push(() => {
setTimeout(() => {
// 加入try、catch 如果执行器中出现错误就调用reject更改状态
try {
// 将回调的结果传给下一个then方法
const x = failCallback(this.reason);
// 判断x的值是普通值还是promise对象,如果是普通值,直接调用resolve
// 如果是promise对象,查看promise对象返回的结果,根据结果决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 调用下一个promise的reject方法
reject(e);
}
}, 0)
});
}
});
return promise2
}
finally(callback) {
// 调用then方法拿到当前promise的状态
return this.then(value => {
// 调用MyPromise.resolve处理callback()返回的结果,并返回
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.resolve(callback()).then(() => { throw reason })
})
}
catch (failCallback) {
return this.then(undefined, failCallback)
}
static all(array) {
let result = [];
// 为了等待异步任务的执行结果 我们定义一个index 当 index和数组的长度相等,说明所有任务都已完成
let index = 0;
return new MyPromise((resolve, reject) => {
const addData = (key, value) => {
result[key] = value;
index++;
if (index === array.length) {
resolve(result);
}
}
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof MyPromise) {
// promise 对象
current.then(value => addData(i, value), reason => reject(reason))
} else {
// 普通值
addData(i, array[i]);
}
}
})
}
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value))
}
}
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
// 自己返回自己 返回reject
reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
// 是promise对象
// x.then(value => { resolve(value) }, reason => { reject(reason) }) 相当于 x.then(resolve,reject)
x.then(resolve, reject)
} else {
// 是普通值 直接返回
resolve(x)
}
}
module.exports = MyPromise;
这样一个Promise就实现完成了!
- 文章内容输出来源:拉勾教育前端高薪训练营;