手写Promise源码
有理解不对的地方求指点,一起沟通交流。
思路
1、根据Promise最初的语法糖,创建MyPromise class类。
2、使用constructor 接受new MyPromise传入函数能立即执行。
3、执行resolve和reject:
传入的函数中能执行resolve和reject ,是因为在new的时候传的函数有两个形参,这个函数接受两个形参只接受函数,你才能resolve() | reject(),可以name(‘df’)的都是方法,方法来源是在执行这个函数的时候,MyPromise 将成功和失败需要的方法传入给这个函数,让new MyPromise时传入的立即执行函数自行根据当前请求状态去调用。
在执行resolve的时候,能在MyPromise 类中的 resolve方法能接受resolve传入的成功值,在执行resolve的时候能接受失败的原因。
4、在执行resolve和reject的时候,需要将将等待改成对应的状态,一旦改变当前承诺不能再变:
pending ==> fulfilled 等待 =》改成成功
pending ==> rejected 等待 =》改成失败
由此,我需要记录当前承诺的状态
不为等待的状态时,说明当前的状态已经改变,使用return结束当前函数,阻止执行。
5、Promise 有个then方法,可以接受两个参数,成功的回调函数和失败的回调函数,其实就是根据状态来调用的。
其实就是跟上面记录的判断来坐处理,如果当前状态是成功,则调用then的第一个参数,失败则调用then的第二个参数。
|
|
上面5个步骤可以实现最基础的Promise基本功能
6、处理异步状态:
当then不为成功和失败就等待的状态。
将then的回调函数在等待的状态时存起来,在resolve或者reject时执行调用then的回调函数。
7、链式调用 (主要关注两点)
第一:在then执行的时候返回 MyPromise 对象实现链式调用;
第二:在then中的三个状态的执行放到返回的MyPromise对象中,使用resolve或reject接受回调函数的返回值做为参数作为下个then的参数。
8、then链式调用返回Promise
对then 传入的回调执行返回值做个判断,如果返回值是 MyPromise 则对值使用.then进行处理,如果是普通值,则直接resolve.
使用 instanceof 来判断。
9、then 链式调用返回自身照常循环调用
使用then执行返回new MyPromise 的时候用变量接受,这个变量跟then返回的值进行 === 对比,如果一样说明对象的引用地址是一样,是同一个对象,调用reject(new Error()) 抛出错误。
正常肯定是比不了的,因为new MyPromise时的变量是在new执行后才能拿到的结果,而判断是在new 执行中;
使用setTimeout 将判断包裹起来,不是为定时执行,是为了将代码变成异步代码。
10、MyPromise 异常处理
在MyPromise 的 constructor 中使用try catch包裹传入的执行函数,将代码放到try catch中监听错误,异常则调用reject。
在then的成功和失败的状态执行时,使用try catch将成功和失败要执行的代码块包裹起来,异常则调用reject。
11、then可选参数处理
当then接受的实参不是 函数的时候使用,当前形参的值为 val => val,then失败的参数不为函数时,则在返回的函数中抛出异常 err => {throw err}
12、实现all功能的实现
从promise的语法中可以得出最基本的几点:
能通过Promise.all,可以证明它是静态方法。
能同时处理几个请求和接受的参数上看,all只接受数组,可以通instanceof 准确判断数组
(instanceof优点可以判断引用类型不能准确判断基本数据类型)
所有的请求为真则为真,一个请求为假返回失败的值。
所以:
创建一个静态的方法;
对接受值做判断处理:
创建一个数组存放all返回的值;
接受的值必须是数组,不为数组抛出错误;
如果接受的值是空数组,则返回空数组;
如果接受的是没有包含异步的请求的数组,执行循环遍历,碰到有异步的原生,则.then进行解析它,为真时往数组push,为失败则停止调用,然后返回失败值,不管前面多少个成功,都返回失败。
当异步成功执行完毕,判断当前push后的数组长度是否跟传入的all数组的长度一样,一样说明所有异步执行完毕了
13、Promise.resolve和Promise.reject 功能的实现:
语法可以看出这两个方法都是静态方法。
它们都是返回Promise。
根据静态方法调用对应的状态。
14、实现finally方法
不管成功还是失败都能调用这个finally方法。
只接受函数作为参数。返回MyPromise对象。
从只能通过new 返回的变量才调用可以看出是原型方法不是静态方法。
15、catch的功能
只接受失败的回调函数,成功的回调函数无需传入函数。
创建Promise 类
Promise代码
从 new Promise()可以看出,Promise是一个构造函数对象
MyPromise代码
class MyPromise()
传入函数 能立即执行
Promise代码
从promise的使用中可以发现,Promise的参数是一个函数,而且函数体是立即执行的,我们也需要传入一个函数进来,并且带了resolve和reject的形参函数
new Promise((resolve, reject) => {
})
MyPromise 代码
在new Promise 时,传入一个函数,使用constructor接受这个这个函数, 来做立即执行
//通过打应111,我们可以得出,通过使用constructor构造器立即执行传过来的函数
class MyPromise{
constructor(execute){ //这个execute接受的值就是new MyPromise 中从中传的函数
console.log(execute) //(resolve, jeject) => {console.log(111)}
execute();//打印111
}
}
new MyPromise((resolve, reject) => {
console.log(111)
})
执行resolve和reject
Promise 代码
参考Promise 语法中看resolve()和reject(),可以得出它们都是一个函数,能传参立即执行
new Promise((resolve, reject) => {
resolve('成功了')
})
MyPromise 代码
核心:resolve和reject是在传入MyPromise执行的,在new Promise()的时候 传入的函数接受两个函数作为参数,函数的来源在MyPromise的内部定义了resolve,和reject两个方法,在请求结果下来的时候调用。
class MyPromise{
constructor(execute){
// execute() //会让调用的resolve报错 resolve is not a function
execute(value => {
//正常打印,不会报错,说明是将MyPromise的代码拿到new MyPromise里去执行,我们就可以定义两个语义化的函数名称,入下面的优化效果代码
// console.log("我来验证猜想");
//既然没错,尝试传参
console.log(value); //打印 成功了,拿到了resolve传入的值
})
}
}
const myProm = new MyPromise((resolve, reject) => {
console.log(111)
/**
* 1、resolve所在的函数传入到了constructor构造器里,而且resolve和reject是通过传参传进的函数。
* 2、执行的时候没传参数当然就啥都没有,等于undefined(),当然报错,传入参数验证猜想
* 3、经过接受到的值,可以确定execute在执行的时候要传入两个方法,可以在MyPromise中实现两个实例方法
*/
resolve("成功了")
console.log(reject)
})
优化效果
class MyPromise{
constructor(execute){
//execute(resolve, reject); //resolve is not defined 还是报错,为什么嘞,class里调用需要this
execute(this.resolve, this.reject)
}
resolve = res => {
console.log(res)
}
reject = error => {
console.log(error)
}
}
new MyPromise((resolve, reject) => { //promise的状态一旦改变不能再变不能输出成功又输出失败
resolve('成功了') //正常打印成功的值 成功了
reject('失败了') //正常打印失败原因 失败了
})
承诺状态改变不能再变
Promise 代码
Promise 代码,只输出1,不管执行多少遍resolve都是只执行一遍,reject也是一样。
const prom = new Promise((resolve, reject) => {
resolve('成功')
resolve('成功')
reject('失败')
})
prom.then(val=> {
console.log(1)
},err=> {
console.log(err)
})
MyPromise 代码
核心:其实就是定义三个状态:分别为等待、成功和失败,当当前状态为等待的情况下,根据new立即执行函数的调用,执行后将状态改变,不为等待的状态去执行,直接return 结束。
//为不执行两遍、重复执行。
//只能从等待改成成功,等待改成失败,那就需要一个记录当前的状态
//录,有三个状态
const pendind = 'PENDING'; //等待
const fulfilled = 'FULFILLED'; // 成功
const rejected = 'REJECTED'; //失败
class MyPromise{
status = 'PENDING' //默认状态为等待状态
constructor(execute){
execute(this.resolve, this.reject)
}
resolve = res => {
//不为等待状态return,说明状态一改不能再改
if(this.status !== pendind) return; //不是等待状态不让执行
this.status = fulfilled; //在等待状态下将等待状态改成成功状态
console.log(res)
}
reject = err => {
//不为等待状态return,说明状态一改不能再改
if(this.status !== pendind) return; //不是等待状态不让执行
this.status = rejected; //在等待状态下将等待状态改成失败状态
console.log(err);
}
}
new MyPromise((resolve, reject) => {
resolve('成功了');
resolve('成功了');
reject('失败了')
})
then实现回调
Promise代码
const prom = new Promise((resolve, reject) => {
resolve('成功了');
reject('失败了')
})
//根据成功状态调用对应回调函数
prom.then(res => {
console.log(res)
}, err => {
console.log(err)
})
MyPromise 实现
核心:就是在MyPromise 中定义了then方法,在then方法中根据当前MyPromise的状态决定是调用then的第一个方法还是第二个方法,将成功或者失败的值传递给这个then的回调函数。。
//定义三个状态
const pending = 'PENDING'; //定义等待的状态
const fulfilled = 'FULFILLED'; //定义成功的状态
const rejected = 'REJECTED'; //定义失败的状态
class MyPromise{
status = pending; //默认状态为等待
successValue = undefined; //用于记录成功的值
failureError = undefined; //用于记录失败的原因
constructor(execute){
execute(this.resolve, this.reject)
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successValue = res; //将成功的值记录
console.log(res)
}
reject = error => {
if(this.status !== pending) return;
this.status = rejected;
this.failureError = error;
console.log(error)
}
then = (success, failure) => {
//console.log('调用then方法了'); //(1、)测试成功
//两个都打印了肯定不对,只能打印一个,而且得根据当前的状态来判断调用哪个(2、)
//success('then调用成功的回调函数咯')
//failure('then调用失败的回调函数咯')
//根据定义的status的状态来调用,但是会输出undefined,需要成功的值和失败的原因传进来
//if(this.status == fulfilled) success(); //会输出 undefined
//if(this.status == rejected) failure(); //会输出undefined
//在上面调用resolve的时候记录成功的值,在调用reject的时候记录失败的原因,作为这里的函数实参
//if(this.status === fulfilled) success(this.successValue);
//if(this.status === rejected) failure(this.failureError);
//改下可读性
if(this.status === fulfilled) { //成功状态的时候执行,【用于处理同步代码】
success(this.successValue);
}else if(this.status === rejected) { //失败后的执行,【用于处理同步的代码】
failure(this.failureError);
}
}
}
const MyProm = new MyPromise((resolve, reject) => { //定义了就不会报then 不是方法的错误了
//resolve('成功了,传入值');
//reject('失败了,传入失败原因');
reject(new Error('参数错误'));
//setTimeout(() => {
// reject(new Error('参数错误'));
//}, 1000)
})
//MyProm.then() //MyProm.then is not a function 需要在里面定义一个then方法
MyProm.then(res => {
console.log("then的成功回调值", res);
}, err => {
console.log("then的失败回调值", err);
})
缺点:虽然基本版本的promise实现了,但是你会发现这段代码使用setTimeout 的时候, then 根本没有执行,直白的说的异步代码根本没啥效果,在异步(setTimeout)的时候不执行,在同步的时候(没有加setTimeout)却可以。看下面的代码解决这个问题
处理异步状态
Promise 代码
Promise 模拟实现异步代码
const prom = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 1000)
})
prom.then(res => {
console.log(res)
}, error => {
console.log(error)
})
MyPromise 实现
通过setTimeout模拟异步等待接口
核心:通过在等待的状态时,将then的函数存起来,等在调用resolve或者reject的时候调用回调函数来实现这个功能。
const pinding = 'PENDING'; //等待的状态
const fulfilled = 'FULFILLED'; //成功的状态
const rejected = 'REJECTED'; //失败的状态
class MyPromise{
status = pinding;
successValue = undefined;
failureError = undefined;
successCallBack = undefined; //将then 成功的回调函数存存起来
failCallback = undefined; // 将then 失败的回调函数存起立
constructor(execute){
execute(this.resolve, this.reject)
}
resolve = res => {
if(this.status !== pinding) return;//只有等待状态才能改变
this.status = fulfilled;//用于将等待状态改变成成功状态
this.successValue = res;
this.successCallBack && this.successCallBack(res) // 在等待状态的时候,异步代码结束后调用resolve函数的时候,执行then的回调函数
}
reject = error => {
if(this.status !== pinding) return;//只有等待状态才能改变
this.status = rejected;//用于将等待状态改变成失败状态
this.failureError = error;
this.failCallback && this.failCallback(error) // 在等待状态的时候,异步代码结束后调用reject函数的时候,执行then的回调函数
}
then = (success, failure) => {
//根据状态来调用
if(this.status === fulfilled){
success(this.successValue);
} else if(this.status === rejected) {
failure(this.failureError);
} else { //在上面的基础我们需要对等待的状态进行处理,如果是等待状态,我们需要将then的函数存起来【不为成功和失败,说明当前状态为等待,也就是处理异步代码】
this.sucssessCallBark = success; //在等待的状态时,将then的成功回调函数缓存起来
this.failCallback = failure; //在等待的状态时,将then的失败回调函数缓存起来
}
}
}
const prom = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(new Error('失败了'))
}, 1000)
setTimeout(() => {
resolve('成功了')
}, 1000)
})
prom.then(res => {
console.log("then",res)
}, error => {
console.log('error',error)
})
确定:但是上面的代码却不能将一个promise返回对象 多次调用。
多次调用then
一个Promise 返回的promise对象是可以同时被多个then调用的
Promise 代码
promise 代码,多个then的时候能同时打印,而我们MyPromise却不行,只能执行一次
const prom = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 2000)
})
prom.then(res => {
console.log(1,res)
},error => {
console.log(error)
})
prom.then(res => {
console.log(2,res)
},error => {
console.log(error)
})
prom.then(res => {
console.log(3,res)
},error => {
console.log(error)
})
MyPromise 代码
MyPromise 实现同一个promise对象可以同时调用
核心是:在异步等待的状态时,分别将成功的和失败的回调函数push在数组中,分别在成功或者失败的时候调用各自的回调函数列表,达到异步的效果,其实就是使用数组去循环执行回调函数列表的
const pending = "PENDING"; // 等待状态
const fulfilled = 'FULFILLED'; // 成功状态
const rejected = 'REJECTED'; // 失败状态
class MyPromise{
status = pending;
successValue = undefined;
fulfilError = undefined;
//将缓存then的属性值改成数组,才能存多个回调函数
successCallBark = [];
//将缓存then的属性值改成数组,才能存多个回调函数
fulfilCallBark = [];
constructor(execute){
execute(this.resolve, this.reject)
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successValue = res;
//this.successCallBack && this.successCallBack(res); //改了数组就不能这样写了
//得用循环来实现
while(this.successCallBark.length){ //存储的回调函数数组不为空的时候才执行
//shift没次从数组中取出第一个回调函数去执行,知道最后一个被取出执行,循环结束
this.successCallBark.shift()(res);
}
}
reject = error => {
if(this.status !== pending) return;
this.status = rejected;
this.fulfilError = error;
//is.failCallback && this.failCallback(error); // //改了数组就不能这样写了
//跟成功的逻辑是一个,只不过是简写的方式
while(this.fulfilCallBark.length) this.fulfilCallBark.shift()(error)
}
then = (succerrCallBark, failureCallBark) => {
if(this.status === fulfilled) { //处理同步代码
succerrCallBark(this.successValue)
} else if(this.status === rejected) { //处理同步代码
failureCallBark(this.fulfilError)
} else { //对异步等待状态代码进行缓存等待执行
//对异步代码做处理,你要等待或者执行多个回调函数就需要数组,将上面存储函数的undefined改成数组
this.successCallBark.push(succerrCallBark)
this.fulfilCallBark.push(failureCallBark)
}
}
}
const prom = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 1000)
})
prom.then(res => {
console.log('res1', res)
}, error => {
console.log('err1',error)
})
prom.then(res => {
console.log('res2', res)
}, error => {
console.log('err2',error)
})
prom.then(res => {
console.log('res3', res)
}, error => {
console.log('err3',error)
})
但是上面的代码又不支持then链式调用。
then链式调用
需要能返回then和能接上一个then的值
Promise代码
const prom = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
})
})
prom.then((res) => {
console.log(res)
return res;
}).then(value => {
console.log(value)
})
MyPromise代码
核心:then能链式调用需要返回MyPromise对象;then能接受到上一个then的返回值用resolve(将值传给下个then),这个值就说then回调函数的执行的返回值。
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successValue = undefined;
rejectError = undefined;
fulfillCall = [];
rejectCall = [];
constructor(execute){
console.log(execute)
execute(this.resolve, this.reject)
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successValue = res;
while(this.fulfillCall.length) {
let he = this.fulfillCall.shift()(res);
}
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectError = err;
while(this.rejectCall.length) this.rejectCall.shift()(err);
}
then = (fulfilledCallBark, rejectCallBark) => {
// if(this.status === fulfilled) {
// console.log(this.status)
// fulfilledCallBark(this.successValue)
// } else if(this.status === rejected) {
// rejectCallBark(this.rejectError)
// } else {
// this.fulfillCall.push(fulfilledCallBark);
// this.rejectCall.push(rejectCallBark)
// }
// 只是 return new MyPromise() 就会报这个错误,因为这个then里return的MyPromise,既然是new Promise就得传立即执行函数呀,但是上面的代码不支持异步
//return new MyPromise() //execute is not a function
//发现fulfilledCallBark 执行的返回值其实就是then的返回值
return new MyPromise((resolve, reject) => { //MyPromise 的这个函数是立即执行的,里面的判断也是立即执行的,直接放到MyPromise里面
if(this.status === fulfilled) {
const val = fulfilledCallBark(this.successValue)
resolve(val)
} else if(this.status === rejected) {
rejectCallBark(this.rejectError)
} else {
this.fulfillCall.push(fulfilledCallBark);
this.rejectCall.push(rejectCallBark)
}
})
}
}
const prom = new MyPromise((resolve, reject) => {
resolve(121)
//reject(new Error('失败了'))
})
const th = prom.then(res => {
console.log('then 成功', res)
return res;
}, err => {
console.log('then 失败', err)
}).then(val => {
console.log("then2成功",val)
})
then链式调用返回Promise对象
其实就是then返回普通值和返回promise做处理,如果是普通值通过resolve将值传给下个then,如果是MyPromise 则进行出现然后再返回给下个then。
Promise
const prom = new Promise((resolve,reject) => {
resolve('成功了')
})
prom.then(res => {
console.log('then1',res)
return new Promise((resolve, reject) => {
resolve('he') //then1 成功了
})
}).then(res => {
console.log('then2', res) //then2 he
})
MyPromise
核心:就是对then的回调函数执行的返回值使用 x instanceof MyPromise做判断,如果是MyPromise对象,则对对象进行处理,如果是普通值直接resolve;
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
execute(this.resolve, this.reject)
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
}
then = (fulfilledCallBark, rejectedCallBark) => {
const prom = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
const val = fulfilledCallBark(this.successVal);
this.resolvePromise(val, resolve, reject);
} else if(this.status == rejected) {
rejectedCallBark(this.rejectErr)
} else {
this.successCall.push(fulfilledCallBark);
this.rejectCall.push(rejectedCallBark);
}
})
return prom;
}
//通过resolve方法进行判断解析
resolvePromise = (x, resolve, reject) => {
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
//x.then(resolve, reject);
}else {
resolve(x);
}
}
}
const prom = new MyPromise((resolve, reject) => {
resolve('成功了')
reject('失败了')
})
prom.then(res => {
console.log("then1", res);
return new MyPromise((resolve, reject) => {
resolve('he');
})
}).then(res => {
console.log('then2', res)
})
处理then返回自身
当Promise 在then返回的时候返回then自己,照成了循环调用问题。
Promise
const prom = new Promise((resolve, reject) => {
resolve('成功了')
})
const pr = prom.then((res) => {
console.log(res); // 成功了
return pr; //Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>
})
pr.then(res => {},err => {
console.log(err.message) //Chaining cycle detected for promise #<Promise>
})
MyPomise
核心:将链式调用创建new MyPromise() 跟then回调函数执行返回MyPromise 进行对比,全等 说明对象的引用是同一个,是同一个对象,就return 阻止 程序继续执行,并抛出异常;new MyPromise() 的执行里面要拿到本身new的结果, 使用setTimeout将代码改成异步代码才能拿到new 的值 ,进行对比
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
execute(this.resolve, this.reject)
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
while(this.successCall.length) this.successCall.shift()(res)
}
reject = err => {
console.log(this.status)
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
while(this.rejectCall.length) this.rejectCall.shift()(err)
}
then = (fulfilledCallBark, rejectedCallBark) => {
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
},0)
} else if(this.status == rejected) {
rejectedCallBark(this.rejectErr)
} else {
this.successCall.push(fulfilledCallBark);
this.rejectCall.push(rejectedCallBark);
}
})
return promise2;
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
console.log(promise2 === x)
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
console.log('执行了')
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
const prom = new MyPromise((resolve, reject) => {
resolve('成功了')
reject('失败了')
})
const pr = prom.then(res => {
console.log("then1", res);
return pr;
})
pr.then(res => { //能连续执行肯定是push,然后在成功和失败的结果下来了调用then的回调函数。
console.log("then2 res",res)
},err => {
console.log("then2Err",err.message)
})
Promise 异常处理
new Promise 立即执行函数异常
Promise
const prom = new Promise((resolve, reject) => {
throw new Error('函数错误了')
})
prom.then((res) => {
console.log(res)
}, err => {
console.log(err)
})
MyPromise
核心:就是在立即执行的 constructor 构造函数中 加入 try catch 处理,报错调用reject(e) ,e就是catch中抛出的异常
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
try{
execute(this.resolve, this.reject)
} catch(e) {
return this.reject(e)
}
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
while(this.successCall.length) this.successCall.shift()(res)
}
reject = err => {
console.log(this.status)
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
while(this.rejectCall.length) this.rejectCall.shift()(err)
}
then = (fulfilledCallBark, rejectedCallBark) => {
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
},0)
} else if(this.status == rejected) {
setTimeout(() => {
const errVal = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, errVal, resolve, reject);
}, 0)
} else {
this.successCall.push(fulfilledCallBark);
this.rejectCall.push(rejectedCallBark);
}
})
return promise2;
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
const prom = new MyPromise((resolve, reject) => {
throw new Error('错误啦')
resolve('成功了')
reject('失败了')
})
const pr = prom.then(res => {
console.log("then1 res", res);
return pr;
}, err => {
console.log("then1 err",err)
})
then 回调函数执行异常
Promise
const prom = new Promise((resolve, reject) => {
resolve('成功了')
})
prom.then(res => {
console.log("then1 res", res)
throw new Error('then1 错误了');
}, err => {
console.log("then1 err",err);
}).then(res => {
console.log("then2 res", res)
}, err => {
console.log("then2 err",err);
})
MyPromise
不管是成功还是失败的回调函数在执行的时候发生错误,使用try catch包裹监听错误,使用setTimeout将代码包裹,使得代码成为异步代码,在代码异常的时候reject(trycatch的异常)
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
try{
execute(this.resolve, this.reject)
} catch(e) {
return this.reject(e)
}
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
while(this.successCall.length) this.successCall.shift()(res)
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
while(this.rejectCall.length) this.rejectCall.shift()(err)
}
then = (fulfilledCallBark, rejectedCallBark) => {
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
//如果then的回调函数中抛出异常,则在成功状态下添加try catch进行异常处理,异常reject(e) e则是执行then中成功回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
},0)
} else if(this.status == rejected) {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
} else {
this.successCall.push(fulfilledCallBark);
this.rejectCall.push(rejectedCallBark);
}
})
return promise2;
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
const prom = new MyPromise((resolve, reject) => {
reject('失败了')
resolve('成功了')
})
prom.then(res => {
console.log("then1 res----", res)
//throw new Error('then1 错误了');
}, err => {
console.log("then1 err",err);
throw new Error('then1 出现错误了');
}).then(res => {
console.log("then2 res", res)
}, err => {
console.log("then2 err",err);
})
then异步链式调用
MyPromise
核心是在等待的状态时,将回调函数列表push 箭头函数,当调用resolve或者reject的时候调用执行对应的函数,执行函数的定时器,异步执行
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
try{
execute(this.resolve, this.reject)
} catch(e) {
return this.reject(e)
}
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
//then 链式异步调用的时候,不需要传参
while(this.successCall.length) this.successCall.shift()()
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
//then 链式异步调用的时候,不需要传参
while(this.rejectCall.length) this.rejectCall.shift()()
}
then = (fulfilledCallBark, rejectedCallBark) => {
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
//如果then的回调函数中抛出异常,则在成功状态下添加try catch进行异常处理,异常reject(e) e则是执行then中成功回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
},0)
} else if(this.status == rejected) {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
} else {
this.successCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
this.rejectCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
}
})
return promise2;
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
const prom = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject('失败了')
}, 2000)
// resolve('成功了')
})
prom.then(res => {
console.log("then1 res----", res)
//throw new Error('then1 错误了');
}, err => {
console.log("then1 err",err);
// throw new Error('then1 出现错误了');
return 'then err 返回错误'
}).then(res => {
console.log("then2 res", res)
}, err => {
console.log("then2 err",err);
})
then 可选参数处理
Promise
核心:then() 里面的实参必须是函数,不是函数都无视它,包括对象,promise 的对象无视它,它们都会被替换为 val => val,所以它们等价于 prom.then(1).then(val => val).then(val => val).then(res => console.log(res))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s8EROlEz-1626512257982)(C:\Users\TOM\Desktop\1609986899iH4e4F.png)]
const prom = new Promise((resolve, reject) => {
resolve('成功了')
})
prom.then(1).then(Promise.resolve(2)).then(res => console.log(res))
MyPromise
核心:只有then没传参或者实参不是函数,统统替换成val => val,使用typeof可以准确判断函数类型。
typeof虽然能准确判断基本类型,但是null 是基本类型,是js的bug,但typeof判断引用类型不准确,唯独function这个对象可以准确判断。
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
try{
execute(this.resolve, this.reject)
} catch(e) {
return this.reject(e)
}
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
//then 链式异步调用的时候,不需要传参
while(this.successCall.length) this.successCall.shift()()
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
//then 链式异步调用的时候,不需要传参
while(this.rejectCall.length) this.rejectCall.shift()()
}
then = (fulfilledCallBark, rejectedCallBark) => {
//只要不是函数,都无视它,替换成val => val
fulfilledCallBark = (fulfilledCallBark && typeof(fulfilledCallBark) === "function") ? fulfilledCallBark : val => val;
rejectedCallBark = (rejectedCallBark && typeof(rejectedCallBark) === "function") ? rejectedCallBark : err => {throw err};
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
//如果then的回调函数中抛出异常,则在成功状态下添加try catch进行异常处理,异常reject(e) e则是执行then中成功回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
},0)
} else if(this.status == rejected) {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
} else {
this.successCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
this.rejectCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
}
})
return promise2;
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
const prom = new MyPromise((resolve, reject) => {
// setTimeout(() => {
// reject('失败了')
// }, 2000)
resolve('成功了')
})
prom.then(1).then(Promise.resolve(2)).then().then(Promise.resolve(1)).then(res => console.log('连续then',res), err => {console.log(err)})
promise.all 功能的实现
Promise
function fun1 () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 1000)
})
}
function fun2 () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 2200)
})
}
function fun3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败了')
}, 1200)
})
}
Promise.all([fun2(), fun2(), fun3()]).then(res => {
console.log(res)
}, err => {
console.log(err)
})
MyPromise
核心:
1、从Promise.all([]).then() 中可以看出,all是一个静态方法,值只能接受数组类型,返回promise 接受处理的值,所有的为真才调用成功回调,一个失败则结束调用失败回调。
2、接受空数组返回空数组。
3、当前数组的不是MyPromise的时,往结果值push,如果是MyPromise对象,则使用then获取该Promise的值,根据状态来操作,成功则往结果数组push值,结果值长度是否传入值的长度是否一致,一致说明all的同步和异步执行完毕了,否则没有继续等待下个异步,如果是失败的promise,直接结束,因为一个失败后面异步怎么成功也是没有用的。
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
try{
execute(this.resolve, this.reject)
} catch(e) {
return this.reject(e)
}
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
//then 链式异步调用的时候,不需要传参
while(this.successCall.length) this.successCall.shift()()
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
//then 链式异步调用的时候,不需要传参
while(this.rejectCall.length) this.rejectCall.shift()()
}
then = (fulfilledCallBark, rejectedCallBark) => {
//只有不是函数,都无视它,替换成val => val
fulfilledCallBark = (fulfilledCallBark && typeof(fulfilledCallBark) === "function") ? fulfilledCallBark : val => val;
rejectedCallBark = (rejectedCallBark && typeof(rejectedCallBark) === "function") ? rejectedCallBark : err => {throw err};
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
//如果then的回调函数中抛出异常,则在成功状态下添加try catch进行异常处理,异常reject(e) e则是执行then中成功回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
},0)
} else if(this.status == rejected) {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
} else {
this.successCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
this.rejectCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
}
})
return promise2;
}
//实现all 的方法
static all (arr) {
if(arr instanceof Array) {
if(arr.length === 0) return arr;
const resultArr = [];
const arrLen = arr.length;
const prom = new Promise((resolve, reject) => {
while(arr.length) {
const current = arr.shift();
if(current instanceof MyPromise){
current.then(res => {
resultArr.push(res);
if(arrLen == resultArr.length) {
resolve(resultArr)
}
}, err => {
reject(err);
return err;
})
} else {
resultArr.push(current);
}
}
})
return prom;
}else {
throw new Error(`${typeof(arr)} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
const prom = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject('失败了1 异步')
}, 4000)
// resolve('成功了1 同步')
})
const prom2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功了2 异步')
}, 4000)
// reject('失败了2 同步')
})
const prom3 = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject('失败了3 异步')
}, 4000)
// resolve('成功了3 同步')
})
const prom4 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功了4 同步')
}, 9000)
})
function fun(){}
MyPromise.all([1, [], {}, fun, '11', prom, prom2, prom3, prom4]).then(res => {
console.log("成功了",res)
}, err => {
console.log("失败了",err)
})
Primise.resolve 功能的实现
Promise
Promise.resolve(1).then().then(console.log, console.log)
MyPromise
核心:
resolve是静态方法;
resolve内部调用了MyPromise对象的resolve,并接受resolve静态方法的值;
可以连续then,明显就是又返回了一个MyPromise对象。
核心代码:
static resolve (val) {
if(val instanceof MyPromise) return val; //如果是MyPromise对象,返回就可以。如果是普通值则创建一个Promise返回
return new MyPromise((resolve, reject) => {
resolve(val)
})
}
完整代码:
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
try{
execute(this.resolve, this.reject)
} catch(e) {
return this.reject(e)
}
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
//then 链式异步调用的时候,不需要传参
while(this.successCall.length) this.successCall.shift()()
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
//then 链式异步调用的时候,不需要传参
while(this.rejectCall.length) this.rejectCall.shift()()
}
then = (fulfilledCallBark, rejectedCallBark) => {
//只有不是函数,都无视它,替换成val => val
fulfilledCallBark = (fulfilledCallBark && typeof(fulfilledCallBark) === "function") ? fulfilledCallBark : val => val;
rejectedCallBark = (rejectedCallBark && typeof(rejectedCallBark) === "function") ? rejectedCallBark : err => {throw err};
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
//如果then的回调函数中抛出异常,则在成功状态下添加try catch进行异常处理,异常reject(e) e则是执行then中成功回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
},0)
} else if(this.status == rejected) {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
} else {
this.successCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
this.rejectCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
}
})
return promise2;
}
//实现all 的方法
static all (arr) {
if(arr instanceof Array) {
if(arr.length === 0) return arr;
const resultArr = [];
const arrLen = arr.length;
const prom = new Promise((resolve, reject) => {
while(arr.length) {
const current = arr.shift();
if(current instanceof MyPromise){
current.then(res => {
resultArr.push(res);
if(arrLen == resultArr.length) {
resolve(resultArr)
}
}, err => {
reject(err);
return err;
})
} else {
resultArr.push(current);
}
}
})
return prom;
}else {
throw new Error(`${typeof(arr)} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
}
static resolve (val) {
if(val instanceof MyPromise) return val; //如果是MyPromise对象,返回就可以。如果是普通值则创建一个Promise返回
return new MyPromise((resolve, reject) => {
resolve(val)
})
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
MyPromise.resolve(1).then().then(res => {
console.log(res);
}, err => {
console.log(err)
})
Promise.reject 功能实现
Promise
Promise.reject(1).then().then(res => {
console.log(res);
}, err => {
console.log(err)
})
MyPromise
核心:其实就是跟Promise.resolve是一样的道理
核心代码
static reject (err) {
if(err instanceof MyPromise) return err; //如果是MyPromise对象,返回就可以。如果是普通值则创建一个Promise返回
return new MyPromise((resolve, reject) => {
reject(err)
})
}
完整代码
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
try{
execute(this.resolve, this.reject)
} catch(e) {
return this.reject(e)
}
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
//then 链式异步调用的时候,不需要传参
while(this.successCall.length) this.successCall.shift()()
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
//then 链式异步调用的时候,不需要传参
while(this.rejectCall.length) this.rejectCall.shift()()
}
then = (fulfilledCallBark, rejectedCallBark) => {
//只有不是函数,都无视它,替换成val => val
fulfilledCallBark = (fulfilledCallBark && typeof(fulfilledCallBark) === "function") ? fulfilledCallBark : val => val;
rejectedCallBark = (rejectedCallBark && typeof(rejectedCallBark) === "function") ? rejectedCallBark : err => {throw err};
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
//如果then的回调函数中抛出异常,则在成功状态下添加try catch进行异常处理,异常reject(e) e则是执行then中成功回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
},0)
} else if(this.status == rejected) {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
} else {
this.successCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
this.rejectCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
}
})
return promise2;
}
//实现all 的方法
static all (arr) {
if(arr instanceof Array) {
if(arr.length === 0) return arr;
const resultArr = [];
const arrLen = arr.length;
const prom = new Promise((resolve, reject) => {
while(arr.length) {
const current = arr.shift();
if(current instanceof MyPromise){
current.then(res => {
resultArr.push(res);
if(arrLen == resultArr.length) {
resolve(resultArr)
}
}, err => {
reject(err);
return err;
})
} else {
resultArr.push(current);
}
}
})
return prom;
}else {
throw new Error(`${typeof(arr)} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
}
static resolve (val) {
if(val instanceof MyPromise) return val; //如果是MyPromise对象,返回就可以。如果是普通值则创建一个Promise返回
return new MyPromise((resolve, reject) => {
resolve(val)
})
}
static reject (err) {
if(err instanceof MyPromise) return err; //如果是MyPromise对象,返回就可以。如果是普通值则创建一个Promise返回
return new MyPromise((resolve, reject) => {
reject(err)
})
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
MyPromise.resolve(1).then().then(res => {
console.log(res);
}, err => {
console.log(err)
})
MyPromise.resolve().then().then(res => {
console.log(res);
}, err => {
console.log(err)
})
MyPromise.reject("失败了").then(res => {
console.log(res)
}, err => {
console.log("失败then1 err", err)
})
Promise 中finally 方法的实现
Promise
const prom = new Promise((resolve, reject) => {
resolve('成功')
})
prom.finally(() => {
console.log("finally");
}).then(res => {
console.log(res);
}, err => {
console.log(err)
}).finally(() => {
console.log("finally2");
})
MyPromise
核心:
1、可以看出finally它不是静态是方法,是原型方法。
2、finally 返回then的结果
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
try{
execute(this.resolve, this.reject)
} catch(e) {
return this.reject(e)
}
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
//then 链式异步调用的时候,不需要传参
while(this.successCall.length) this.successCall.shift()()
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
//then 链式异步调用的时候,不需要传参
while(this.rejectCall.length) this.rejectCall.shift()()
}
then = (fulfilledCallBark, rejectedCallBark) => {
//只有不是函数,都无视它,替换成val => val
fulfilledCallBark = (fulfilledCallBark && typeof(fulfilledCallBark) === "function") ? fulfilledCallBark : val => val;
rejectedCallBark = (rejectedCallBark && typeof(rejectedCallBark) === "function") ? rejectedCallBark : err => {throw err};
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
//如果then的回调函数中抛出异常,则在成功状态下添加try catch进行异常处理,异常reject(e) e则是执行then中成功回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
},0)
} else if(this.status == rejected) {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
} else {
this.successCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
this.rejectCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
}
})
return promise2;
}
//实现all 的方法
static all (arr) {
if(arr instanceof Array) {
if(arr.length === 0) return arr;
const resultArr = [];
const arrLen = arr.length;
const prom = new Promise((resolve, reject) => {
while(arr.length) {
const current = arr.shift();
if(current instanceof MyPromise){
current.then(res => {
resultArr.push(res);
if(arrLen == resultArr.length) {
resolve(resultArr)
}
}, err => {
reject(err);
return err;
})
} else {
resultArr.push(current);
}
}
})
return prom;
}else {
throw new Error(`${typeof(arr)} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
}
finally = (callBark) => {
return this.then(res => {
if(typeof(callBark) === 'function') {
return MyPromise.resolve(callBark()).then(res => res)
}
}, err => {
return MyPromise.reject(callBark()).then(() => {throw err})
})
}
static resolve (val) {
if(val instanceof MyPromise) return val; //如果是MyPromise对象,返回就可以。如果是普通值则创建一个Promise返回
return new MyPromise((resolve, reject) => {
resolve(val)
})
}
static reject (err) {
if(err instanceof MyPromise) return err; //如果是MyPromise对象,返回就可以。如果是普通值则创建一个Promise返回
return new MyPromise((resolve, reject) => {
reject(err)
})
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
function fun1() {
return new MyPromise((resolve, reject) => {
resolve('成功1')
// reject("失败")
// setTimeout(() => {
// resolve('成功')
// reject("失败")
// }, 6000)
})
}
function fun2 () {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功222')
// reject("失败")
}, 5000)
})
}
// fun1().finally(() => {
// console.log("finally");
// }).then(res => {
// console.log('then1',res);
// return fun2();
// }, err => {
// console.log(err)
// }).finally(() => {
// console.log("finally2");
// }).then(res => {
// console.log("then2 成",res);
// return res;
// }, err => {
// console.log("then2 败",err)
// }).finally(() => {
// console.log("finally3");
// }).then(res => {
// console.log("then3 成",res);
// }, err => {
// console.log("then3 败",err)
// })
fun1().finally(() => {
console.log("finally");
return fun2();
}).then(res => {
console.log('then1',res);
}, err => {
console.log(err)
})
Promise.catch方法的实现
Promise
const prom = new Promise((resolve, reject) => {
reject("失败了")
})
prom.then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
MyPromise
核心代码
catch (callBark) {
return this.then(undefined,callBark);
}
完整代码
const pending = 'PENDING';
const fulfilled = 'FULFILLED';
const rejected = 'REJECTED';
class MyPromise{
status = pending;
successVal = undefined;
rejectErr = undefined;
successCall = [];
rejectCall = [];
constructor(execute){
try{
execute(this.resolve, this.reject)
} catch(e) {
return this.reject(e)
}
}
resolve = res => {
if(this.status !== pending) return;
this.status = fulfilled;
this.successVal = res;
//then 链式异步调用的时候,不需要传参
while(this.successCall.length) this.successCall.shift()()
}
reject = err => {
if(this.status !== pending) return;
this.status = rejected;
this.rejectErr = err;
//then 链式异步调用的时候,不需要传参
while(this.rejectCall.length) this.rejectCall.shift()()
}
then = (fulfilledCallBark, rejectedCallBark) => {
//只有不是函数,都无视它,替换成val => val
fulfilledCallBark = (fulfilledCallBark && typeof(fulfilledCallBark) === "function") ? fulfilledCallBark : val => val;
rejectedCallBark = (rejectedCallBark && typeof(rejectedCallBark) === "function") ? rejectedCallBark : err => {throw err};
const promise2 = new MyPromise((resolve, reject) => {
if(this.status == fulfilled){
//这里加定时不是为了延迟,而是让这段代码成为异步代码
//在这里想拿到promise2是new MyPromise执行结束后才能拿到,而这里是执行的时候拿是拿不到的,需要将这段代码改成异步代码
setTimeout(() => {
//如果then的回调函数中抛出异常,则在成功状态下添加try catch进行异常处理,异常reject(e) e则是执行then中成功回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
},0)
} else if(this.status == rejected) {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
} else {
this.successCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = fulfilledCallBark(this.successVal);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
this.rejectCall.push(() => {
setTimeout(() => {
// 如果then的回调函数中 失败回调函数出现异常,则在失败状态下添加try catch进行异常处理,异常reject(e), e 则是执行then中失败回调函数时出现的错误
try{
const value = rejectedCallBark(this.rejectErr);
this.resolvePromise(promise2, value, resolve, reject);
} catch(e) {
reject(e)
}
}, 0)
});
}
})
return promise2;
}
//实现all 的方法
static all (arr) {
if(arr instanceof Array) {
if(arr.length === 0) return arr;
const resultArr = [];
const arrLen = arr.length;
const prom = new Promise((resolve, reject) => {
while(arr.length) {
const current = arr.shift();
if(current instanceof MyPromise){
current.then(res => {
resultArr.push(res);
if(arrLen == resultArr.length) {
resolve(resultArr)
}
}, err => {
reject(err);
return err;
})
} else {
resultArr.push(current);
}
}
})
return prom;
}else {
throw new Error(`${typeof(arr)} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
}
finally = (callBark) => {
return this.then(res => {
if(typeof(callBark) === 'function') {
return MyPromise.resolve(callBark()).then(res => res)
}
}, err => {
return MyPromise.reject(callBark()).then(() => {throw err})
})
}
catch (rejectedCallBark) {
return this.then(undefined, rejectedCallBark);
}
static resolve (val) {
if(val instanceof MyPromise) return val; //如果是MyPromise对象,返回就可以。如果是普通值则创建一个Promise返回
return new MyPromise((resolve, reject) => {
resolve(val)
})
}
static reject (err) {
if(err instanceof MyPromise) return err; //如果是MyPromise对象,返回就可以。如果是普通值则创建一个Promise返回
return new MyPromise((resolve, reject) => {
reject(err)
})
}
//通过resolve方法进行判断解析
resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x){
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if(x instanceof MyPromise) {
//Promise对象
//x.then(res => resolve(res), err => reject(err))
x.then(resolve, reject);
}else {
resolve(x);
}
}
}
function fun1() {
return new MyPromise((resolve, reject) => {
// resolve('成功1')
reject("失败")
})
}
fun1().then(res => console.log('then1',res)).catch(err => {
console.log(err)
})