在ES6出来之后,有很多关于Promise的讲解、文章,也有很多经典的书籍讲解Promise.
那么这里我从几个实际的例子来作为切入点:
【任何一个新技术的出来,就是用来解决原有技术的某一个痛点】
//request.js
function requestData(url){
// 模拟网络请求
setTimeout(()=>{
//拿到请求的1结果
//url传入的是 coderwhy,请求成功
if(url==="coderwhy"){
let names=["wjy","hyz","tqy"];
return names;//* 但其实这个return外面是拿不到结果的
}else{// 否则请求失败
let errMessage="请求失败,url错误";
return errMessage;//* 但其实这个return外面是拿不到结果的
}
},3000)
}
// main.js
requestData("coderwhy")
修改requestData参数,需要传入成功的回调函数successCallback和失败的回调函数failCallback。
//request.js
function requestData(url,successCallback,failCallback){
// 模拟网络请求
setTimeout(()=>{
//拿到请求的1结果
//url传入的是 coderwhy,请求成功
if(url==="coderwhy"){
let names=["wjy","hyz","tqy"];
successCallback(names);
}else{// 否则请求失败
let errMessage="请求失败,url错误";
failCallback(errMessage)
}
},3000)
}
// main.js
requestData("coderwhy",(res)=>{
console.log("成功:",res);
},(err)=>{
console.log("失败:",err);
})
那么有没有一种更好的方式:
// * 更好的方案 承诺(规范好了所有的代码编写逻辑)
function requestData2(){
return "承诺"
}
const chengnuo=requestData2()
Promise是ES6新增的一个API,它是一个类,可以翻译成 承诺、许诺、期约;
当我们需要给予调用者一个承诺:待会儿我会传给你回调数据时,就可以创建一个Promise对象
在通过new 创建Promise对象时,我们需要传入一个回调函数,我们称之为executor
function foo(){
// Promise
return new Promise((resolve,reject)=>{
// resolve();
reject();
})
}
// main.js
const fooPromise=foo();
// * then方法传入的回调函数,会在Promise执行resolve函数时,会回调。
fooPromise.then(()=>{
})
// * catch方法传入的回调函数,会在Promise执行reject函数时,被回调
fooPromise.catch(()=>{
})
// class Person{
// constructor(callback){
// function foo(){
// }
// function bar(){
// }
// callback(foo,bar)
// }
// }
// const p=new Person((foo,bar)=>{
// foo();
// bar()
// });
// * Promise是一个类,可以传入参数,参数是回调函数,这个回调函数在传入时,会立即被执行。
/**
* * 传入的回调函数可以称之为 executor
* * 这个回调函数会有两个参数:
* * resolve :成功时,执行resolve回调
* * reject:失败时,执行reject回调
*/
const promise=new Promise((resolve,reject)=>{
// console.log("promise传入的函数立即被执行了");
resolve();
})
promise.then(()=>{
})
promise.catch(()=>{
})
/**
* * 回调的弊端
* * 1.如果是我们自己封装的requestData,那么我们在封装的时候必须要自己设计好callback名称,并且使用好
* * 2.如果我们使用的是别人封装的requestData或者一些第三方库,那么我们必须去看别人的源码或者文档,才知道这个函数怎么去获取结果的。
* * 3.这种沟通成本非常多的
*/
//request.js
function requestData(url,successCallback,failCallback){
// 模拟网络请求
return new Promise((resolve,reject)=>{
setTimeout(()=>{
//拿到请求的1结果
//url传入的是 coderwhy,请求成功
if(url==="coderwhy"){
let names=["wjy","hyz","tqy"];
resolve(names);
}else{// 否则请求失败
let errMessage="请求失败,url错误";
reject(errMessage)
}
},3000);
})
}
//main.js
const promise=requestData("coderwhy");
// * then方法传入两个回调函数
// * 第一个回调函数,会在Promise执行resolve函数时,被回调
// * 第二个回调函数,会在Promise执行reject函数时,被回调
promise.then((res)=>{
console.log("请求成功:",res);
},(err)=>{
console.log("请求失败了:",err);
})
// 完全等价于下面的代码
new Promise((resolve,reject)=>{
console.log("------------------");//* 阶段:pending
resolve();
}).then(res=>{
console.log("res:",res);//* fulfilled(固定、已敲定)
},err=>{
console.log("err:",err);//* rejected (已拒绝 )
})
上面的Promise使用过程,我们可以将它划分成三个状态:
待定(pending):初始状态,既没有被兑现,也没有被拒绝
已兑现(fulfilled):意味着操作成功完成
已拒绝(rejected):意味着操作失败
Promise状态一旦被确定下来,那么就是不可更改的(锁定),例如下面我们先执行了resolve,将状态改为 已兑现(fulfilled)。后面又执行了reject,企图将状态修改为已拒绝(rejected),但发现其实并不能进行修改的。
// * Promise状态一旦被确定下来,那么就是不可更改的(锁定)
new Promise((resolve,reject)=>{
console.log("------------------");//* 阶段:pending
resolve();//* fulfilled(固定、已敲定)
reject();////* rejected (已拒绝 ) ,这行代码没有任何意义。
// resolve(123)
}).then(res=>{
console.log("res:",res);
},err=>{
console.log("err:",err);
})
/**
* resolve(参数)
* * (1)普通的值或者对象
* * (2)传入一个Promise
* * 那么当前的Promise状态由传入的Promise来决定
* * 相当于状态进行了移交
* * (3)传入一个对象,并且这个对象有实现的then方法 (thenable),那么也会执行该then方法,并且由该then方法决定后续状态
*/
// * 传入Promise的特殊情况
// const newPromise=new Promise((resolve,reject)=>{
// // resolve("aaaaa")
// reject("err message")
// })
// new Promise((resolve,reject)=>{
// resolve(newPromise)
// }).then(res=>{
// console.log("res:",res);
// },err=>{
// console.log("err:",err);
// })
//* 2.传入一个对象,这个对象有实现then方法,由该then方法决定后续状态
new Promise((resolve,reject)=>{
const obj={
then:function(resolve,reject){
// resolve("resolve message");
reject("reject message")
}
}
resolve(obj);
}).then(res=>{
console.log("res:",res);
},err=>{
console.log("err:",err);
})
then方法是Promise对象的一个方法,它其实是 放在Promise的原型上的Promise.prototype.then
then方法接受两个参数:
promise.then(res=>{
console.log("res:",res);
},err=>{
console.log("err:",err);
})
// 等价于下面
promise.then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
})
同一个promise对象的then方法可以调用多次。
当resolve方法被回调时,所有传入到then方法的回调函数会执行。
// * Promise有哪些对象方法
// console.log(Promise.prototype);
// console.log(Object.getOwnPropertyDescriptors(Promise.prototype));
const promise=new Promise((resolve,reject)=>{
resolve("hahahaha")
})
// *同一个promise可以多次调用then方法
// * 当我们的resolve方法被回调时,所有的then方法传入的回调函数都会被调用
promise.then((res)=>{
console.log("res:",res);
})
promise.then((res)=>{
console.log("res2:",res);
})
promise.then((res)=>{
console.log("res3:",res);
})
其实then方法有返回值,返回的是新的Promise对象
then方法的回调函数也有返回值,当then方法中的回调函数返回一个结果时,那么它处于fulfilled状态,并且会将结果作为resolve的参数
如果返回的是一个普通的值(数字、字符串、对象),这个值会作为then方法返回的Promise对象的resolve的值
如果没有返回值,则默认返回的是undefined
const promise=new Promise((resolve,reject)=>{
resolve("hahahaha")
})
promise.then(res=>{
// *如果回调函数没有返回值,则返回的是一个undefined
return {name:"wjy"}
}).then(res=>{
console.log("res:",res);
})
如果返回的是一个Promise对象,
const promise=new Promise((resolve,reject)=>{
resolve("hahahaha")
})
// *如果返回的是一个Promise对象
promise.then(res=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("hello wjy")
},3000)
})
}).then(res=>{
console.log("res:",res);
})
// *如果返回了是一个对象,并且这个对象上
promise.then(res=>{
return { //* new Promise(resolve=>resolve(obj.then))
then:function(resolve,reject){
resolve(2222)
}
}
}).then(res=>{
console.log("res:",res);
})
then方法内部可以传入两个参数(两个回调函数)
当resolve函数被执行时,会调用then方法的第一个参数(回调函数)
当reject函数被执行时,会调用then方法的第二个参数(回调函数)【或者内部发生错误,也会被then方法的第二个参数捕获到。】
const promise=new Promise((resolve,reject)=>{
reject("rejected status")
})
promise.then(undefined,err=>{
console.log("err:",err);
})
const promise=new Promise((resolve,reject)=>{
throw new Error("rejected status")
})
promise.then(undefined,err=>{
console.log("err:",err);
})
如果将成功和失败的回调函数写在一块,阅读性差,比如下面:
const promise=new Promise((resolve,reject)=>{
// reject("rejected status")
throw new Error("rejected status")
})
promise.then(res=>{
console.log("res:",res);
},err=>{
console.log("err:",err);
})
支持另外一种方法:
通过catch方法传入错误或拒绝的捕获的回调函数:
const promise=new Promise((resolve,reject)=>{
reject("rejected status")
})
// * 通过catch方法传入错误或(拒绝)捕获的回调函数
// promise/a+规范
promise.catch(err=>{
console.log("err:",err)
})
还支持另外一种写法:
const promise=new Promise((resolve,reject)=>{
reject("rejected status")
// throw new Error("rejected status")
})
promise.then(res=>{
return 111
}).catch(err=>{
console.log("err:",err)
})
const promise=new Promise((resolve,reject)=>{
resolve("resolve status")
})
promise.then(res=>{
throw new Error("发生错误")
return 111
}).catch(err=>{
console.log("err:",err);//*如果第一个promise对象没有异常,所以就不会执行,等着下一次使用,会给下一个Promise对象使用
console.log("------");
})
// * 拒绝捕获的问题(前面课程)
const promise=new Promise((resolve,reject)=>{
reject("rejected status");//* 有点类似抛出异常
})
promise.then(res=>{
console.log("res:",res);
})
promise.catch(err=>{
console.log("err:",err);
})
这个代码运行后会报错的。
改成下面这种就不会报错:
// * 拒绝捕获的问题(前面课程)
const promise=new Promise((resolve,reject)=>{
reject("rejected status");//* 有点类似抛出异常
})
promise.then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
})
或
const promise=new Promise((resolve,reject)=>{
reject("rejected status");//* 有点类似抛出异常
})
promise.then(res=>{
console.log("res:",res);
},err=>{
console.log("err:",err);
})
如果执行了reject(),throw会被忽略
如果执行了throw,throw后面的代码都不会再执行。
catch方法也是Promise对象上的一个方法,它也是放在Promise的原型上的Promise.prototype.catch方法。
同一个Promise对象的catch方法可以被调用多次
const promise=new Promise((resolve,reject)=>{
reject("aaa");
})
promise.catch(err=>{
console.log("err1:",err);
})
promise.catch(err=>{
console.log("err2:",err);
})
promise.catch(err=>{
console.log("err3:",err);
})
事实上catch方法也是会返回一个Promise对象的,所以catch方法后面我们可以继续调用then方法或者catch方法
const promise=new Promise((resolve,reject)=>{
reject("aaa");
})
promise.then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
return "catch return value"
}).then(res=>{
console.log("res:",res);
})
const promise=new Promise((resolve,reject)=>{
reject("aaa");
})
promise.then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("my name")
},3000)
})
}).then(res=>{
console.log("res:",res);
})
fanally是ES9(ES2018)新增的一个特性:表示无论Promise的状态变为fulfilled还是reject状态,最终都会被执行的代码。
finally方法是不接收参数的,因为无论前面是fulfilled状态,还是reject状态,它都会执行。
const promise=new Promise((resolve,reject)=>{
resolve("resolve message");
})
promise.then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
}).finally(()=>{
console.log("finally code execute");
})
finally其实也是返回一个Promise对象,但是其实很少人会用它
前面我们学习的then、catch、finally方法都属于Promise的实例方法,都是存放在Promise的prototype上的。
下面我们将学习类方法
有时候我们已经有一个现成的内容,希望将其转成Promise来使用,这个时候我们可以使用Promise.resolve方法来完成。
resolve的参数形式:
function foo(){
const obj={name:"wjy"}
return new Promise((resolve)=>{
resolve(obj);
});
}
foo().then(res=>{
console.log("res:",res);
})
等价于下面:
function foo(){
const obj={name:"wjy"}
return Promise.resolve(obj);
}
foo().then(res=>{
console.log("res:",res);
})
// * 1.传入普通的值
// const promise=Promise.resolve({name:"wjy"});
// * 2.传入一个Promise,由这个新的Promise对象决定原Promise对象的状态
// const promise=Promise.resolve(new Promise((resolve,reject)=>{
// // resolve("resolve2 message")
// reject("reject message")
// }))
// promise.then(res=>{
// console.log("res:",res);
// }).catch(err=>{
// console.log("err:",err);
// })
// * 3. 传入thenable对象(实现了then方法),会立即执行then方法,由then方法的结果决定其Promise的状态
const promise=Promise.resolve({
then:function(resolve,reject){
// resolve("resolve ");
reject("reject message")
}
})
promise.then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
})
reject方法类似于resolve方法,只是会将Promise对象的状态设置为rejected状态
Promise.reject的用法相当于new Promise,并且会调用reject
Promise.reject无论传过来的参数是什么状态,都会直接作为reject的参数传递到catch的。
它的作用是将多个Promise包裹在一起,形成一个新的Promise
新的Promise状态由包裹的所有Promise决定
const p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(1111)
},1000)
})
const p2=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(22222)
},2000)
})
const p3=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(33333)
},3000)
})
// * 需求:所有的Promise都变成fulfilled,再拿到结果
//* 意外:在拿到所有结果之前,有一个promise变成了rejected,那么整个promise是rejected
Promise.all([p1,p2,p3,"aaaa"]).then(res=>{
console.log("res:",res);
}).catch(err=>{
// * 最后转到catch执行
console.log("err:",err);
})
// * all:所有的promise为fulfilled时才会执行then方法,如果有一个状态为rejected,就会转成执行catch方法
all方法有一个缺陷:当有一个Promise变成rejected状态时,新Promise就会立即变成对应的rejected状态。
在ES11(ES2020)中,添加了新的API Promise.allSettled
const p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(1111)
},1000)
})
const p2=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(22222)
},2000)
})
const p3=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(33333)
},3000)
})
// allSettled
// * 新的Promise的状态一定是fulfilled
Promise.allSettled([p1,p2,p3]).then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
})
如果有一个Promise有了结果,我们就希望决定最终新的Promise的状态,那么可以使用race方法
const p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(1111)
},1000)
})
const p2=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(22222)
},2000)
})
const p3=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(33333)
},3000)
})
// * race :竞技 竞赛
Promise.race([p1,p2,p3]).then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
})
any方法是ES12中新增的方法,和race方法是类似的:
const p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(1111)
},1000)
})
const p2=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(22222)
},2000)
})
const p3=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(33333)
},3000)
})
// * any
Promise.any([p1,p2,p3]).then(res=>{
console.log("res:",res);
}).catch(err=>{
// *可以通过.errors拿到合计的错误信息
console.log("err:",err.errors);
})
const PROMISE_STATUS_PENDING="pending";
const PROMISE_STATUS_FULFILLED="fulfilled";
const PROMISE_STATUS_REJECTED="rejected";
// * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
class HYPromise{
// * 记录状态
constructor(executor) {
// * 保存Promise的状态
this.status=PROMISE_STATUS_PENDING;
// * 保存传入的值
this.value=undefined;
this.reason=undefined;
const resolve=(value)=>{
if(this.status==PROMISE_STATUS_PENDING){
this.status=PROMISE_STATUS_FULFILLED;
this.value=value;
console.log("resolve被调用");
}
}
const reject=(reason)=>{
if(this.status==PROMISE_STATUS_PENDING){
this.status=PROMISE_STATUS_REJECTED;
this.reason=reason;
console.log("reject被调用");
}
}
executor(resolve,reject)
}
}
const promise=new HYPromise((resolve,reject)=>{
console.log("状态pending");
resolve("1111")
})
const PROMISE_STATUS_PENDING="pending";
const PROMISE_STATUS_FULFILLED="fulfilled";
const PROMISE_STATUS_REJECTED="rejected";
// * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
class HYPromise{
// * 记录状态
constructor(executor) {
// * 保存Promise的状态
this.status=PROMISE_STATUS_PENDING;
// * 保存传入的值
this.value=undefined;
this.reason=undefined;
const resolve=(value)=>{
if(this.status==PROMISE_STATUS_PENDING){
this.status=PROMISE_STATUS_FULFILLED;
queueMicrotask(()=>{ //* 定时器是一个宏任务,会放在下一次事件循环时使用
this.value=value;
console.log("resolve被调用");
// * 执行then传入进来的第一个回调函数
this.onFulfilled(this.value)
})
}
}
const reject=(reason)=>{
if(this.status==PROMISE_STATUS_PENDING){
this.status=PROMISE_STATUS_REJECTED;
queueMicrotask(()=>{
this.reason=reason;
console.log("reject被调用");
// * 执行then传入进来的第二个回调函数
this.onRejected(this.reason);
})
}
}
executor(resolve,reject)
}
then(onFulfilled,onRejected){
this.onFulfilled=onFulfilled;
this.onRejected=onRejected;
}
}
const promise=new HYPromise((resolve,reject)=>{
console.log("状态pending");
// resolve("1111")
reject("reject message")
})
promise.then(res=>{
console.log("res:",res);
},err=>{
console.log("err:",err);
})
promise.then(res=>{
console.log("res2:",res);
},err=>{
console.log("err2:",err);
})
// * 多次调用then,后面的then方法会覆盖前面的then方法,而且只会调用一次方法
// * then方法不能实现链式调用
const PROMISE_STATUS_PENDING="pending";
const PROMISE_STATUS_FULFILLED="fulfilled";
const PROMISE_STATUS_REJECTED="rejected";
// * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
class HYPromise{
// * 记录状态
constructor(executor) {
// * 保存Promise的状态
this.status=PROMISE_STATUS_PENDING;
// * 保存传入的值
this.value=undefined;
this.reason=undefined;
this.onFulfilledFns=[];
this.onRejectedFns=[];
const resolve=(value)=>{
if(this.status==PROMISE_STATUS_PENDING){
queueMicrotask(()=>{ //* 定时器是一个宏任务,会放在下一次事件循环时使用
this.status=PROMISE_STATUS_FULFILLED;
this.value=value;
console.log("resolve被调用");
// * 执行then传入进来的第一个回调函数
this.onFulfilledFns.forEach(Fn=>{
Fn(this.value)
})
})
}
}
const reject=(reason)=>{
if(this.status==PROMISE_STATUS_PENDING){
queueMicrotask(()=>{
this.status=PROMISE_STATUS_REJECTED;
this.reason=reason;
console.log("reject被调用");
// * 执行then传入进来的第二个回调函数
this.onRejectedFns.forEach(Fn=>{
Fn(this.reason)
})
})
}
}
executor(resolve,reject)
}
then(onFulfilled,onRejected){
// 1.如果then方法调用的时候,状态已经确定下来了,应该直接执行的
if(this.status===PROMISE_STATUS_FULFILLED&&onFulfilled){
onFulfilled(this.value);
}else if(this.status===PROMISE_STATUS_REJECTED&&onRejected){
onRejected(this.reason)
}else{
// 将成功回调和失败回调添加到数组中
this.onFulfilledFns.push(onFulfilled);
this.onRejectedFns.push(onRejected);
}
}
}
const promise=new HYPromise((resolve,reject)=>{
console.log("状态pending");
resolve("1111");//resolved/fulfilled
})
promise.then(res=>{
console.log("res:",res);
},err=>{
console.log("err:",err);
})
promise.then(res=>{
console.log("res2:",res);
},err=>{
console.log("err2:",err);
})
setTimeout(()=>{
promise.then(res=>{
console.log(res);
})
},1000)
// * 解决了then方法的多次调用
// * 在确定Promise状态之后,再次调用then
// const promise2=new Promise((resolve,reject)=>{
// resolve("aaaaa");
// })
// setTimeout(()=>{
// promise2.then(res=>{ //原生编写了
// console.log(res);
// })
// },1000)
const PROMISE_STATUS_PENDING="pending";
const PROMISE_STATUS_FULFILLED="fulfilled";
const PROMISE_STATUS_REJECTED="rejected";
// 工具函数
function execFunctionWithCatchError(exeFn,value,resolve,reject){
try{
let result=exeFn(value);
reject(result);
}catch(err){
reject(err);
}
}
// * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
class HYPromise{
// * 记录状态
constructor(executor) {
// * 保存Promise的状态
this.status=PROMISE_STATUS_PENDING;
// * 保存传入的值
this.value=undefined;
this.reason=undefined;
this.onFulfilledFns=[];
this.onRejectedFns=[];
const resolve=(value)=>{
if(this.status==PROMISE_STATUS_PENDING){
// * 添加微任务
queueMicrotask(()=>{ //* 定时器是一个宏任务,会放在下一次事件循环时使用
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_FULFILLED;
this.value=value;
// console.log("resolve被调用");
// * 执行then传入进来的第一个回调函数
this.onFulfilledFns.forEach(Fn=>{
Fn(this.value);
})
})
}
}
const reject=(reason)=>{
if(this.status==PROMISE_STATUS_PENDING){
// * 添加微任务
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_REJECTED;
this.reason=reason;
// console.log("reject被调用");
// * 执行then传入进来的第二个回调函数
this.onRejectedFns.forEach(Fn=>{
Fn(this.reason)
})
})
}
}
// * 在调用executor时判断里面是否抛出异常
try{
executor(resolve,reject)
}catch(err){
reject(err)
}
}
then(onFulfilled,onRejected){
return new HYPromise((resolve,reject)=>{
// 1.如果then方法调用的时候,状态已经确定下来了,应该直接执行的
if(this.status===PROMISE_STATUS_FULFILLED&&onFulfilled){
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
}else if(this.status===PROMISE_STATUS_REJECTED&&onRejected){
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
}else{
// 将成功回调和失败回调添加到数组中
this.onFulfilledFns.push(()=>{
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
});
this.onRejectedFns.push(()=>{
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
});
}
})
}
}
const promise=new HYPromise((resolve,reject)=>{
// console.log("状态pending");
// resolve("1111");//resolved/fulfilled
reject("2222")
// throw new Error("创建就报的异常")
})
promise.then(res=>{
console.log("res:",res);
return "aaaa"
},err=>{
console.log("err:",err);
return "err bbb"
}).then(res=>{
console.log("res2:",res);
},err=>{
console.log("err2:",err);
})
// * 1. 实现了链式调用,链式调用的前提是返回一个新的HYPromise,最重要的是 什么时候执行resolve,什么时候执行reject
// * 一般在正常情况下,无论原HYPromise的状态是如何,后面都会执行新的HYPromise的resolve,并将其值作为参数
// * 只有在代码发生异常时(错误),才会让新的HYPromise执行reject
// * 2. 在HYPromise的executor执行过程中如果发生异常,应该要执行reject
// * catch方法的设计
catch(onRejected){
this.then(undefined,onRejected);
}
但是这样还是不能捕获原Promise对象的rejected状态,因为这个catch方法是针对新的Promise的rejected的状态,如果想要捕获原Promise的rejected状态,需要抛出异常,新的Promise对象的catch方法才能捕获到。
所以我们需要改写then方法:
这样在新的Promise就能捕获到原来的promise的rejected的状态
then(onFulfilled,onRejected){
onRejected=onRejected||(err=>{throw err})
//以下代码省略...
}
全部的代码如下:
const PROMISE_STATUS_PENDING="pending";
const PROMISE_STATUS_FULFILLED="fulfilled";
const PROMISE_STATUS_REJECTED="rejected";
// 工具函数
function execFunctionWithCatchError(exeFn,value,resolve,reject){
try{
let result=exeFn(value);
reject(result);
}catch(err){
reject(err);
}
}
// * 自己手写的Promise要符合的一定的规范,要符合PromiseA+
class HYPromise{
// * 记录状态
constructor(executor) {
// * 保存Promise的状态
this.status=PROMISE_STATUS_PENDING;
// * 保存传入的值
this.value=undefined;
this.reason=undefined;
this.onFulfilledFns=[];
this.onRejectedFns=[];
const resolve=(value)=>{
if(this.status==PROMISE_STATUS_PENDING){
// * 添加微任务
queueMicrotask(()=>{ //* 定时器是一个宏任务,会放在下一次事件循环时使用
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_FULFILLED;
this.value=value;
// console.log("resolve被调用");
// * 执行then传入进来的第一个回调函数
this.onFulfilledFns.forEach(Fn=>{
Fn(this.value);
})
})
}
}
const reject=(reason)=>{
if(this.status==PROMISE_STATUS_PENDING){
// * 添加微任务
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_REJECTED;
this.reason=reason;
// console.log("reject被调用");
// * 执行then传入进来的第二个回调函数
this.onRejectedFns.forEach(Fn=>{
Fn(this.reason)
})
})
}
}
// * 在调用executor时判断里面是否抛出异常
try{
executor(resolve,reject)
}catch(err){
reject(err)
}
}
then(onFulfilled,onRejected){
onRejected=onRejected||(err=>{throw err})
return new HYPromise((resolve,reject)=>{
// 1.如果then方法调用的时候,状态已经确定下来了,应该直接执行的
if(this.status===PROMISE_STATUS_FULFILLED&&onFulfilled){
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
}else if(this.status===PROMISE_STATUS_REJECTED&&onRejected){
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
}else{
// 将成功回调和失败回调添加到数组中
if(onFulfilled)this.onFulfilledFns.push(()=>{
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
});
if(onRejected)this.onRejectedFns.push(()=>{
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
});
}
})
}
// * catch方法的设计
catch(onRejected){
this.then(undefined,onRejected);
}
}
const promise=new HYPromise((resolve,reject)=>{
console.log("状态pending");
// resolve("1111");//resolved/fulfilled
reject("2222")
// throw new Error("创建就报的异常")
})
promise.then(res=>{
console.log("res:",res);
},err=>{
console.log("err1:",err);
}).catch(err=>{
console.log("err:",err);
})
const PROMISE_STATUS_FULFILLED="fulfilled";
const PROMISE_STATUS_PENDING="pending";
const PROMISE_STATUS_REJECTED="rejected";
// 工具函数
function execFunctionWithCatchError(exeFn,value,resolve,reject){
try{
const result=exeFn(value);
resolve(result);
}catch(err){
reject(err);
}
}
class HYPromise{
constructor(executor){
this.status=PROMISE_STATUS_PENDING;
this.value=undefined;
this.reason=undefined;
// this.onFulfilled=undefined;
// this.onRejected=undefined;
this.onFulfilledFns=[];
this.onRejectedFns=[];
const resolve=(value)=>{
if(this.status==PROMISE_STATUS_PENDING){
// * 原生执行then方法时是一个微任务
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_FULFILLED;
this.value=value;
// * 执行then传入进来的回调函数
// this.onFulfilled(this.value);
this.onFulfilledFns.forEach(Fn=>{
Fn(this.value);
})
})
}
}
const reject=(reason)=>{
if(this.status==PROMISE_STATUS_PENDING){
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_REJECTED;
this.reason=reason;
// * 执行then传入进来的第二个参数
// this.onRejected(this.reason);
this.onRejectedFns.forEach(Fn=>{
Fn(this.reason);
})
})
}
}
try{
executor(resolve,reject)
}catch(err){
reject(err);
}
}
then(onFulfilled,onRejected){
onRejected=onRejected|| (err=>{ throw err});
onFulfilled=onFulfilled|| (value=>value)
return new HYPromise((resolve,reject)=>{
if(this.status==PROMISE_STATUS_FULFILLED&&onFulfilled){
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
}else if(this.status==PROMISE_STATUS_REJECTED&&onRejected){
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
}else{
if(onFulfilled)this.onFulfilledFns.push(()=>{
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
});
if(onRejected)this.onRejectedFns.push(()=>{
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
});
}
})
}
catch(onRejected){
return this.then(undefined,onRejected);
}
finally(onFinally){
return this.then(()=>{
onFinally();
},()=>{
onFinally();
})
}
}
const promise=new HYPromise((resolve,reject)=>{
console.log("状态pending");
// reject("111");
resolve("222");
// throw new Error("pending err")
})
promise.then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("catch err:",err);
}).finally(()=>{
console.log("finally方法实现");
})
// * 实现finally方法
const PROMISE_STATUS_FULFILLED="fulfilled";
const PROMISE_STATUS_PENDING="pending";
const PROMISE_STATUS_REJECTED="rejected";
// 工具函数
function execFunctionWithCatchError(exeFn,value,resolve,reject){
try{
const result=exeFn(value);
resolve(result);
}catch(err){
reject(err);
}
}
class HYPromise{
constructor(executor){
this.status=PROMISE_STATUS_PENDING;
this.value=undefined;
this.reason=undefined;
// this.onFulfilled=undefined;
// this.onRejected=undefined;
this.onFulfilledFns=[];
this.onRejectedFns=[];
const resolve=(value)=>{
if(this.status==PROMISE_STATUS_PENDING){
// * 原生执行then方法时是一个微任务
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_FULFILLED;
this.value=value;
// * 执行then传入进来的回调函数
// this.onFulfilled(this.value);
this.onFulfilledFns.forEach(Fn=>{
Fn(this.value);
})
})
}
}
const reject=(reason)=>{
if(this.status==PROMISE_STATUS_PENDING){
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_REJECTED;
this.reason=reason;
// * 执行then传入进来的第二个参数
// this.onRejected(this.reason);
this.onRejectedFns.forEach(Fn=>{
Fn(this.reason);
})
})
}
}
try{
executor(resolve,reject)
}catch(err){
reject(err);
}
}
then(onFulfilled,onRejected){
onRejected=onRejected|| (err=>{ throw err});
onFulfilled=onFulfilled|| (value=>value)
return new HYPromise((resolve,reject)=>{
if(this.status==PROMISE_STATUS_FULFILLED&&onFulfilled){
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
}else if(this.status==PROMISE_STATUS_REJECTED&&onRejected){
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
}else{
if(onFulfilled)this.onFulfilledFns.push(()=>{
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
});
if(onRejected)this.onRejectedFns.push(()=>{
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
});
}
})
}
catch(onRejected){
return this.then(undefined,onRejected);
}
finally(onFinally){
return this.then(()=>{
onFinally();
},()=>{
onFinally();
})
}
static resolve(value){
return new HYPromise((resolve,reject)=>{
resolve(value);
})
}
static reject(reason){
return new HYPromise((resolve,reject)=>{
reject(reason);
})
}
}
HYPromise.resolve(123).then(res=>{
console.log("res:",res);
})
HYPromise.reject("err message").catch(err=>{
console.log("err:",err);
})
// * 实现了类方法 resolve和reject方法
const PROMISE_STATUS_FULFILLED="fulfilled";
const PROMISE_STATUS_PENDING="pending";
const PROMISE_STATUS_REJECTED="rejected";
// 工具函数
function execFunctionWithCatchError(exeFn,value,resolve,reject){
try{
const result=exeFn(value);
resolve(result);
}catch(err){
reject(err);
}
}
class HYPromise{
constructor(executor){
this.status=PROMISE_STATUS_PENDING;
this.value=undefined;
this.reason=undefined;
// this.onFulfilled=undefined;
// this.onRejected=undefined;
this.onFulfilledFns=[];
this.onRejectedFns=[];
const resolve=(value)=>{
if(this.status==PROMISE_STATUS_PENDING){
// * 原生执行then方法时是一个微任务
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_FULFILLED;
this.value=value;
// * 执行then传入进来的回调函数
// this.onFulfilled(this.value);
this.onFulfilledFns.forEach(Fn=>{
Fn(this.value);
})
})
}
}
const reject=(reason)=>{
if(this.status==PROMISE_STATUS_PENDING){
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_REJECTED;
this.reason=reason;
// * 执行then传入进来的第二个参数
// this.onRejected(this.reason);
this.onRejectedFns.forEach(Fn=>{
Fn(this.reason);
})
})
}
}
try{
executor(resolve,reject)
}catch(err){
reject(err);
}
}
then(onFulfilled,onRejected){
onRejected=onRejected|| (err=>{ throw err});
onFulfilled=onFulfilled|| (value=>value)
return new HYPromise((resolve,reject)=>{
if(this.status==PROMISE_STATUS_FULFILLED&&onFulfilled){
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
}else if(this.status==PROMISE_STATUS_REJECTED&&onRejected){
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
}else{
if(onFulfilled)this.onFulfilledFns.push(()=>{
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
});
if(onRejected)this.onRejectedFns.push(()=>{
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
});
}
})
}
catch(onRejected){
return this.then(undefined,onRejected);
}
finally(onFinally){
return this.then(()=>{
onFinally();
},()=>{
onFinally();
})
}
static resolve(value){
return new HYPromise((resolve,reject)=>{
resolve(value);
})
}
static reject(reason){
return new HYPromise((resolve,reject)=>{
reject(reason);
})
}
static all(promises){
// * 问题关键:什么时候执行resolve,什么时候执行reject
return new HYPromise((resolve,reject)=>{
let values=[];
promises.forEach(promise=>{
promise.then(res=>{
values.push(res);
if(values.length==promises.length) resolve(values);
}).catch(err=>{
reject(err);
})
})
})
}
static allSettled(promises){
return new Promise((resolve)=>{
let results=[];
promises.forEach(promise=>{
promise.then(res=>{
results.push({status:PROMISE_STATUS_FULFILLED,value:res})
if(results.length==promises.length)
resolve(results);
}).catch(err=>{
results.push({status:PROMISE_STATUS_REJECTED,value:err})
if(results.length==promises.length)
resolve(results);
})
})
})
}
}
const p1=new Promise((resolve)=>{
setTimeout(()=>{
resolve(1111)
},1000)
})
const p2=new Promise((resolve)=>{
setTimeout(()=>{
resolve(2222)
},2000)
})
const p3=new Promise((resolve)=>{
setTimeout(()=>{
resolve(3333)
},3000)
})
// *all方法会产生一个新的Promise对象,这个新的Promise对象是由前面的所有的Promise来决定其状态
// * 如果全部为fulfilled,则会执行then方法,如果有一个为rejected,则直接执行catch方法
HYPromise.all([p1,p2,p3]).then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
})
// * allSettled:它会等所有的Promise都有结果,然后再执行resolve方法,它是没有reject方法的执行
// * 实现了all方法:
HYPromise.allSettled([p1,p2,p3]).then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err);
})
const PROMISE_STATUS_FULFILLED="fulfilled";
const PROMISE_STATUS_PENDING="pending";
const PROMISE_STATUS_REJECTED="rejected";
// 工具函数
function execFunctionWithCatchError(exeFn,value,resolve,reject){
try{
const result=exeFn(value);
resolve(result);
}catch(err){
reject(err);
}
}
class HYPromise{
constructor(executor){
this.status=PROMISE_STATUS_PENDING;
this.value=undefined;
this.reason=undefined;
// this.onFulfilled=undefined;
// this.onRejected=undefined;
this.onFulfilledFns=[];
this.onRejectedFns=[];
const resolve=(value)=>{
if(this.status==PROMISE_STATUS_PENDING){
// * 原生执行then方法时是一个微任务
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_FULFILLED;
this.value=value;
// * 执行then传入进来的回调函数
// this.onFulfilled(this.value);
this.onFulfilledFns.forEach(Fn=>{
Fn(this.value);
})
})
}
}
const reject=(reason)=>{
if(this.status==PROMISE_STATUS_PENDING){
queueMicrotask(()=>{
if(this.status!==PROMISE_STATUS_PENDING) return;
this.status=PROMISE_STATUS_REJECTED;
this.reason=reason;
// * 执行then传入进来的第二个参数
// this.onRejected(this.reason);
this.onRejectedFns.forEach(Fn=>{
Fn(this.reason);
})
})
}
}
try{
executor(resolve,reject)
}catch(err){
reject(err);
}
}
then(onFulfilled,onRejected){
onRejected=onRejected|| (err=>{ throw err});
onFulfilled=onFulfilled|| (value=>value)
return new HYPromise((resolve,reject)=>{
if(this.status==PROMISE_STATUS_FULFILLED&&onFulfilled){
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
}else if(this.status==PROMISE_STATUS_REJECTED&&onRejected){
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
}else{
if(onFulfilled)this.onFulfilledFns.push(()=>{
execFunctionWithCatchError(onFulfilled,this.value,resolve,reject);
});
if(onRejected)this.onRejectedFns.push(()=>{
execFunctionWithCatchError(onRejected,this.reason,resolve,reject);
});
}
})
}
catch(onRejected){
return this.then(undefined,onRejected);
}
finally(onFinally){
return this.then(()=>{
onFinally();
},()=>{
onFinally();
})
}
static resolve(value){
return new HYPromise((resolve,reject)=>{
resolve(value);
})
}
static reject(reason){
return new HYPromise((resolve,reject)=>{
reject(reason);
})
}
static all(promises){
// * 问题关键:什么时候执行resolve,什么时候执行reject
return new HYPromise((resolve,reject)=>{
let values=[];
promises.forEach(promise=>{
promise.then(res=>{
values.push(res);
if(values.length==promises.length) resolve(values);
}).catch(err=>{
reject(err);
})
})
})
}
static allSettled(promises){
return new HYPromise((resolve)=>{
let results=[];
promises.forEach(promise=>{
promise.then(res=>{
results.push({status:PROMISE_STATUS_FULFILLED,value:res})
if(results.length==promises.length)
resolve(results);
}).catch(err=>{
results.push({status:PROMISE_STATUS_REJECTED,value:err})
if(results.length==promises.length)
resolve(results);
})
})
})
}
static race(promises){
return new HYPromise((resolve,reject)=>{
promises.forEach(promise=>{
// promise.then(res=>{
// resolve(res);
// }).catch(err=>{
// reject(err);
// })
promise.then(resolve,reject)
})
})
}
static any(promises){
// * resolve必须等待有一个成功的结果
// * reject 所有的都失败才执行 reject
return new HYPromise((resolve,reject)=>{
let count=0;
let reasons=[];
promises.forEach(promise=>{
promise.then(res=>{
resolve(res)
}).catch(err=>{
reasons.push(err);
if(reasons.length==promises.length){
// reject(reasons)
reject(new AggregateError(reasons," AggregateError: All promises were rejected"))
}
})
})
})
}
}
// const p1=new Promise((resolve)=>{
// setTimeout(()=>{
// resolve(1111)
// },1000)
// })
// const p2=new Promise((resolve)=>{
// setTimeout(()=>{
// resolve(2222)
// },2000)
// })
// const p3=new Promise((resolve)=>{
// setTimeout(()=>{
// resolve(3333)
// },3000)
// })
// HYPromise.race([p1,p2,p3]).then(res=>{
// console.log("res:",res);
// }).catch(err=>{
// console.log("err:",err);
// })
// * any方法
const p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(1111)
},1000)
})
const p2=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(2222)
},2000)
})
const p3=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(3333)
},3000)
})
HYPromise.any([p1,p2,p3]).then(res=>{
console.log("res:",res);
}).catch(err=>{
console.log("err:",err.errors);
})