文章内容输出来源:拉勾教育大前端高薪训练营
1、核心逻辑
定义promise三种状态 pending rejected fulfilled
通过resolve和rejected方法改变状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
//执行器
executor(this.resolve, this.rejected)
}
// 初始状态
status = PENDING;
// 成功后的值
value = undefined;
// 失败的原因
err = undefined;
resolve = (value) => {
this.status = FULFILLED;
this.value = value
}
rejected = (err) => {
this.status = REJECTED
this.err = err;
}
then(successCb, failCb) {
successCb(this.value)
failCb(this.err)
}
}
let promise = new MyPromise((resolve, reject) => {
resolve('1000')
}).then(res => {
console.log(res);
}, err => {
console.log(err);
})
2、异步逻辑
状态是等待的时候 ,将成功回调和失败的回调保存起来。
当异步代码执行完毕后,调用resolve或reject时,判断成功或失败的回调是否存在。
resolve = (value) => {
if(this.status!==PENDING) return;
this.status = FULFILLED;
this.value = value
this.successCb && this.successCb(this.value)
}
rejected = (err) => {
if(this.status!==PENDING) return;
this.status = REJECTED
this.err = err;
this.failCb&& this.failCb(this.err)
}
then(successCb, failCb) {
if(this.status===FULFILLED){
successCb(this.value)
}else if(this.status===REJECTED){
failCb(this.err)
}else{
// 等待的状态
//将失败或成功的回调保存起来
this.successCb = successCb;
this.failCb = failCb;
}
}
3、then方法多次调用
将成功或失败的回调保存到一个数组中。
// 成功回调
successCb = []
//失败回调
failCb = [];
resolve = (value) => {
if(this.status!==PENDING) return;
this.status = FULFILLED;
this.value = value
// this.successCb && this.successCb(this.value)
while (this.successCb.length) {
this.successCb.shift()(this.value)
}
}
rejected = (err) => {
if(this.status!==PENDING) return;
this.status = REJECTED
this.err = err;
// this.failCb&& this.failCb(this.err)
while (this.failCb.length) {
this.failCb.shift()(this.err)
}
}
then(successCb, failCb) {
// 成功
if(this.status===FULFILLED){
successCb(this.value)
}else if(this.status===REJECTED){
failCb(this.err)
}else{
// 等待的状态
//将失败或成功的回调保存起来
this.successCb.push(successCb) ;
this.failCb.push(failCb);
}
}
5、then链式调用
通过在then方法return 一个promise
then(successCb, failCb) {
let promise2 = new MyPromise((resolve, reject) => {
// 成功
if (this.status === FULFILLED) {
let x = successCb(this.value)
resolve(x)
} else if (this.status === REJECTED) {
let y = failCb(this.err)
reject(y)
} else {
// 等待的状态
//将失败或成功的回调保存起来
this.successCb.push(successCb);
this.failCb.push(failCb);
}
})
return promise2;
}
6、错误捕捉
循环引用的错误
function resolvePromise(promise2,x,resolve,reject) {
if(promise2 === x){
return reject(new TypeError('promise实例重复引用了'))
}
if(x instanceof MyPromise){
x.then(resolve,reject)
}else{//普通值
resolve(x)
}
}
constructor(executor) {
try {
//执行器
executor(this.resolve, this.rejected)
} catch (error) {
this.rejected(error)
}
}
7、then方法参数可选
successCb = successCb?successCb:value=>value
failCb = failCb?failCb:err=>{throw err}
8、all方法实现
static all(arr) {
let result = [];
let index = 0;
return new MyPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value;
index++;
if (index === arr.length) {
resolve(result)
}
}
for (let i = 0; i < arr.length; i++) {
let cur = arr[i]
if (cur instanceof MyPromise) {
cur.then(val => addData(i, val), err => reject(err))
} else {
addData(i, arr[i])
}
}
})
}
9、resolve方法实现
static resolve(value){
if(value instanceof MyPromise){
return value
}else{//包装成promise对象
return new MyPromise((resolve)=>resolve(value))
}
}
10、finally方法实现
finally(cb){
return this.then(value=>{
return MyPromise.resolve(cb()).then(()=>value)
},err=>{
return MyPromise.resolve(cb()).then(()=>{throw err})
})
}
11、catch方法实现
catch(cb) {
return this.then(undefined, cb)
}
完整代码:
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.rejected)
} catch (error) {
this.rejected(error)
}
}
// 状态
status = PENDING;
// 成功后的值
value = undefined;
// 失败后的原因
err = undefined;
// 成功回调
successCb = [];
// 失败回调
failCb = []
resolve = value => {
if (this.status !== PENDING) return
this.status = FULFILLED;
this.value = value;
// this.successCb && this.successCb(this.value)
while (this.successCb.length) {
this.successCb.shift()()
}
}
rejected = err => {
if (this.status !== PENDING) return
this.status = REJECTED;
this.err = err;
// this.failCb && this.failCb(this.err)
while (this.failCb.length) {
this.failCb.shift()()
}
}
then(successCb, failCb) {
successCb = successCb ? successCb : value => value;
failCb = failCb ? failCb : err => { throw err }
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = successCb(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCb(this.err)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else {
//等待
this.successCb.push(() => {
setTimeout(() => {
try {
let x = successCb(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
});
this.failCb.push(() => {
setTimeout(() => {
try {
let x = failCb(this.err)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
});
}
})
return promise2;
}
catch(cb){
return this.then(undefined,cb)
}
finally(cb) {
return this.then(value => {
return MyPromise.resolve(cb()).then(() => value);
}, err => {
return MyPromise.resolve(cb()).then(() => { throw err })
})
}
static all(arr) {
let result = [];
let index = 0;
return new MyPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value;
index++;
if (index === arr.length) {
resolve(result)
}
}
for (let i = 0; i < arr.length; i++) {
let current = arr[i];
if (current instanceof MyPromise) {
current.then(value => addData(i, value), err => reject(err))
} else {
addData(i, arr[i])
}
}
})
}
static resolve(value) {
if (value instanceof MyPromise) {
return value
} else {
return new MyPromise((resolve) => resolve(value))
}
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('重复引用了'))
}
if (x instanceof MyPromise) {
// x.then(value=>resolve(value),err=>reject(err))
x.then(resolve, reject)
} else {
resolve(x)
}
}
// 以下是测试代码
let promise = new MyPromise((resolve, reject) => {
// setTimeout(() => {
resolve('OK')
// reject('err')
// }, 1000)
})
promise.then().then().then(resolve => console.log(resolve), err => {
console.log(err);
})
function p1() {
return new MyPromise((resolve) => {
setTimeout(() => {
resolve('p1')
}, 2000)
})
}
function p2() {
return new MyPromise((resolve) => {
resolve('p2')
})
}
p2().finally(()=>{
console.log('finally');
}).then(res=>{
console.log(res);
},err=>{
console.log(err);
})
MyPromise.all(['a', 'b', p1(), p2(), 'c']).then(res => {
console.log(res);
})
MyPromise.resolve(100).then(res => console.log(res))
// function other() {
// return new MyPromise((resolve, reject) => {
// resolve('other')
// })
// }
// let p1 = promise.then(value => {
// // throw new Error('自定义then错误')
// console.log(value);
// // return p1;
// }, err => {
// console.log(err);
// return 1000
// })
// promise.then(value=>{
// console.log(value);
// },err=>{
// console.log(err);
// })
// lagou
// Promise {pending}
// Promise {resolve}
// hello
// lala
// undefined
// lala