一、Promise的三种状态
promise有三种状态:pending
(待处理)、fufilled
(成功)、rejected
(失败)
1.promise
初始状态为:pending
(待处理)
2.promise
执行完resolve
时状态为:fufilled
(成功)
3.promise
执行完reject
时状态为:rejected
(失败)
看下面例子:
二、实现resolve与reject
resolve
与reject
是promise
execute
中的两个类型为函数的形参,作用分别是:
resolve
:调用resolve
认定promise
为成功
reject
:调用reject
认定promise
为失败
实现代码:
class MyPromise{
//函数构造器
constructor(execute){
//初始promise状态
this.state='pending'
//result为保存promise结果值
this.result=null
try{
//执行execute(执行器)
execute(this.resolve,this.reject)
}catch (err){
this.reject(err)
}
}
//实现resolve
resolve=(value)=>{
//加判断是因为promise状态只更改一次
if(this.state==='pending'){
//当状态为pending是修改为fulfilled
this.state='fulfilled'
//保存成功promise的结果值
this.result=value
}
}
reject=(reason)=>{
if(this.state==='pending'){
//当状态为pending是修改为reject
this.state='rejected'
//保存失败promise的结果值
this.result=reason
}
}
}
复制代码
测试一下以上代码:
const test1 = new MyPromise((resolve,reject)=>{
resolve(100)
})
const test2 = new MyPromise((resolve,reject)=>{
reject(200)
})
console.log('test1:',test1,'test2:',test2)
复制代码
结果:
三、实现then
1. then
有两个参数,一个接收promise
成功的情况的回调(onResolve
),一个接收promise
失败的情况的回调(onRejected
)
2. 当promise
状态为fulfilled
时执行成功的情况的回调
3. 当promsie
状态为rejected
时执行失败情况的回调
4. then
有两个参数分别是onResolve
、onRejected
-
onResolve
: 是成功情况的回调,它有一个参数接收成功promise
的结果 -
onRejected
: 是失败情况的回调,它有一个参数接收失败promise
的结果
实现代码:
then(onResolve,onReject){
//判断onResolve是不是函数,如果不是则直接返回
onResolve = typeof onResolve==="function"?onResolve:value=>value
//判断onReject是不是函数,如果不是则把传进来的参数直接扔出报错
onReject = typeof onReject==="function"?onReject:reason=>{throw reason}
//状态为fulfilled则执行成功回调
if(this.state==='fulfilled'){
onResolve(this.result)
}
//状态为rejected则执行失败回调
else if(this.state === 'rejected'){
onReject(this.result)
}
}
复制代码
测试以上代码:
const test1 = new MyPromise((resolve,reject)=>{
resolve(100)
})
test1.then(value=>{
console.log(value)
})
const test2 = new MyPromise((resolve,reject)=>{
reject(200)
})
test2.then(value=>{},reason=>{
console.log(reason)
})
复制代码
结果:
如果是定时器状况呢?
如这样的:
怎么样才可以保证1秒后在then里面执行并接收到结果呢?
答:很简单我们暂时把onResolve和onRejected保存起来,等待peomise的状态为fulfilled或rejected再执行相应的回调即可
实现步骤:
1.首先要在constructor
里初始化两个空数组
constructor(execute){
//初始promise状态
this.state='pending'
//result为保存promise结果值
this.result=null
//用于保存then中的onResolved回调
this.onResolvedCallbacks=[]
//用于保存then中的onRejected回调
this.onRejectedCallbacks=[]
try{
//执行execute(执行器)
execute(this.resolve,this.reject)
}catch (err){
this.reject(err)
}
}
复制代码
2.promise
状态为pending
时then
则暂时保存onResolve
与onRejected
then(onResolve,onReject){
//判断onResolve是不是函数,如果不是则直接返回
onResolve = typeof onResolve==="function"?onResolve:value=>value
//判断onReject是不是函数,如果不是则把传进来的参数直接扔出报错
onReject = typeof onReject==="function"?onReject:reason=>{throw reason}
//状态为fulfilled则执行成功回调
if(this.state==='fulfilled'){
onResolve(this.result)
}
//状态为rejected则执行失败回调
else if(this.state === 'rejected'){
onReject(this.result)
}
//当状态为pending时则暂时保存onResolve与onReject
else if(this.state === 'pending'){
this.onResolvedCallbacks.push(()=>{
onResolve(this.result)
})
this.onRejectedCallbacks.push(()=>{
onReject(this.result)
})
}
}
复制代码
3.在resolve
与reject
中拉出每一个保存的回调进行调用
//实现resolve
resolve=(value)=>{
//加判断是因为promise状态只更改一次
if(this.state==='pending'){
//当状态为pending是修改为fulfilled
this.state='fulfilled'
//保存成功promise的结果值
this.result=value
//遍历每一个保存的成功回调并调用再删除
while (this.onResolvedCallbacks.length>0){
this.onResolvedCallbacks.shift()()
}
}
}
//实现reject
reject=(reason)=>{
if(this.state==='pending'){
//当状态为pending是修改为reject
this.state='rejected'
//保存失败promise的结果值
this.result=reason
//遍历每一个保存的失败回调并调用再删除
while (this.onRejectedCallbacks.length>0){
this.onRejectedCallbacks.shift()()
}
}
}
复制代码
测试以上代码:
const test1 = new MyPromise((resolve,reject)=>{
setTimeout(()=>{
resolve(100)
},1000)
})
test1.then(value=>{
console.log(value)
})
const test2 = new MyPromise((resolve,reject)=>{
setTimeout(()=>{
reject(200)
},2000)
})
test2.then(value=>{},reason=>{
console.log(reason)
})
复制代码
结果:
四、then微任务
then是微任务的,所以我们要给then加上一个定时器,让它异步执行即可
实现代码:
then(onResolve,onReject){
//判断onResolve是不是函数,如果不是则直接返回
onResolve = typeof onResolve==="function"?onResolve:value=>value
//判断onReject是不是函数,如果不是则把传进来的参数直接扔出报错
onReject = typeof onReject==="function"?onReject:reason=>{throw reason}
//添加定时器让then异步执行
setTimeout(()=>{
//状态为fulfilled则执行成功回调
if(this.state==='fulfilled'){
let x = onResolve(this.result)
}
//状态为rejected则执行失败回调
else if(this.state === 'rejected'){
let x = onReject(this.result)
}
//当状态为pending时则保存onResolve与onReject
else if(this.state === 'pending'){
this.onResolvedCallbacks.push(()=>{
let x = onResolve(this.result)
})
this.onRejectedCallbacks.push(()=>{
let x = onReject(this.result)
})
}
},0)
}
复制代码
测试代码:
const p = new MyPromise((resolve,reject)=>{
resolve(100)
})
p.then(value=>{
console.log(value)
})
console.log(200)
复制代码
结果:
五、实现then链式调用
then链式调用是手写promsie中难的
需要知道以下几点:
1.then
返回的是一个promise
,promise
将暴露给后续方法链
简单来说就是then
返回一个promise
,promise
中有then
方法,then
返回一个promise
,promise
中有then
方法,这样就可以无限套娃,就形成了链式调用
2.当一个值只是从一个 then
内部返回时,它将等价地返回 Promise.resolve(<由被调用的处理程序返回的值>)
就是当then
执行onResolve
或onRejecte
时如果onResolve
或onRejecte
有返回值,就执行promsie
中的resolve(onResolve或onRejecte的返回值)
回调
3.如果函数抛出错误或返回一个拒绝的Promise
,则 then
将返回一个拒绝的Promise
。
4.如果 onFulfilled
返回了一个 promise,then
的返回值就会被 Promise resolve 或者 reject。
就是如果onResolve
或onReject
返回值是一个promsie
,then
的返回值就会被Pormise
执行reoslved
或reject
,主要看onResolve
或onReject
返回的promise
是成功的还是失败的,成功的promsie
执行resolve
,失败的promise
执行reject
实现代码:
then(onResolve,onReject){
//判断onResolve是不是函数,如果不是则直接返回
onResolve = typeof onResolve==="function"?onResolve:value=>value
//判断onReject是不是函数,如果不是则把传进来的参数直接扔出报错
onReject = typeof onReject==="function"?onReject:reason=>{throw reason}
const MyPromise2 = new MyPromise((resolve,reject)=>{
try{
//让then异步执行
setTimeout(()=>{
//状态为fulfilled则执行成功回调
if(this.state==='fulfilled'){
//x获取onResolve的返回值
let x = onResolve(this.result)
//调用ResolvePromise并传入返回值x、resolve、reject与MyPromise2
ResolvePromise(x,resolve,reject,MyPromise2)
}
//状态为rejected则执行失败回调
else if(this.state === 'rejected'){
//x获取onReject的返回值
let x = onReject(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
}
//当状态为pending时则保存onResolve与onReject
else if(this.state === 'pending'){
this.onResolvedCallbacks.push(()=>{
let x = onResolve(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
})
this.onRejectedCallbacks.push(()=>{
let x = onReject(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
})
}
},0)
//ResolvePromise是用来判断onResolve与onReject的返回值并做出处理
const ResolvePromise = (x,resolve,reject,promise2) => {
//如果x等于then的返回值则扔出报错
if(x === promise2){
throw new Error('不能返回自身')
}
//如果x是MyPromise实例,则使用.then方法来获取MyPromise的结果
if(x instanceof MyPromise){
x.then(res=>{
resolve(res)
},err=>{
reject(err)
})
}
//如果不是MyPromise实例则直接resolve
else{
resolve(x)
}
}
}catch (err){
reject(err)
throw new Error(err)
}
})
return MyPromise2
}
复制代码
测试代码:
new MyPromise((resolve,reject)=>{
setTimeout(()=>{
resolve(100)
},1000)
}).then(value=>{
console.log(value)
return 200
}).then(value => {
console.log(value)
return new MyPromise((resolve,reject)=>{
reject(300)
})
}).then(value=>{},reason=>{
console.log(reason)
})
复制代码
结果:
六、实现catch
catch
的实现与then
一致,只不过catch
只有onReject
参数,话不多说直接上代码:
//实现catch
catch(onReject){
//判断onReject是不是函数,如果不是则把传进来的参数直接扔出报错
onReject = typeof onReject==="function"?onReject:reason=>{throw reason}
const MyPromise2 = new MyPromise((resolve,reject)=>{
try{
//让then异步执行
setTimeout(()=>{
//状态为rejected则执行失败回调
if(this.state === 'rejected'){
//x获取onReject的返回值
let x = onReject(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
}
//当状态为pending时则保存onResolve与onReject
else if(this.state === 'pending'){
this.onRejectedCallbacks.push(()=>{
let x = onReject(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
})
}
},0)
//ResolvePromise是用来判断onResolve与onReject的返回值并做出处理
const ResolvePromise = (x,resolve,reject,promise2) => {
//如果x等于then的返回值则扔出报错
if(x === promise2){
throw new Error('不能返回自身')
}
//如果x是MyPromise实例,则使用.then方法来获取MyPromise的结果
if(x instanceof MyPromise){
x.then(res=>{
resolve(res)
},err=>{
reject(err)
})
}
//如果不是MyPromise实例则直接resolve
else{
resolve(x)
}
}
}catch (err){
reject(err)
throw new Error(err)
}
})
return MyPromise2
}
复制代码
测试代码:
new MyPromise((resolve,reject)=>{
setTimeout(()=>{
reject(100)
},1000)
}).catch(reason=>{
console.log(reason)
})
复制代码
结果:
七、其他方法
其他方法就挑几个常用方法来写
- 1.resolve
resolve
:方法返回一个以给定值解析后的Promise
对象。
实现也很简单:
//promise resolve方法
static resolve(value){
return new MyPromise((resolve,reject)=>{
resolve(value)
})
}
复制代码
测试以上代码:
MyPromise.resolve(100).then(value=>{
console.log(value)
})
复制代码
结果:
- 2.reject
reject()
方法返回一个带有拒绝原因的Promise
对象。
实现和resolve方法差不多:
static reject(reason){
return new MyPromise((resolve,reject)=>{
reject(reason)
})
}
复制代码
测试代码:
MyPromise.reject(200).catch(reason=>{
console.log(reason)
})
复制代码
结果:
- 3.all
all
:方法接收多个promise
并返回一个promise
,接收的所有promise
的结果都为成功则返回的promise
的结果为所有成功的结果,但接收的所有的promise
中有一个失败的则返回promsie
的结果为失败的结果,如果接收的不是promise
则直接当做成功的结果
注意一个细节:all
接收的promise
返回的所有成功的结果的数组与接收的promise
顺序需要保持一致
实现代码:
//promise all方法
static all(promises){
//保存成功结果
let success = []
//记录保存数量
let count = 0
//返回一个Promise
return new MyPromise((resolve,reject)=>{
//保存成功的结果
const save = (value,index) => {
//用index保存是为了与promises的顺序一致
success[index]=value
// 记录保存数量
count++
//当保存数量与promises一致时说明所有结果都为成功直接resolve
if(count === promises.length) resolve(success)
}
try{
// 遍历promises
promises.forEach((promise,index)=>{
//判断promise中的每一项是不是MyPromise的实例
if(promise instanceof MyPromise){
promise.then(res=>{
//成功的promise则保存结果
save(res,index)
},err=>{
//失败的直接reject
reject(err)
})
}else{
//不是MyPromise直接为成功进行保存
save(promise,index)
}
})
}catch (err){
reject(err)
throw new Error(err)
}
})
}
复制代码
测试以上代码:
function test1(){
const test1=new MyPromise((resolve,reject)=>{
setTimeout(()=>{
resolve(100)
})
})
const test2=new MyPromise((resolve,reject)=>{
resolve(200)
})
const test3=new MyPromise((resolve,reject)=>{
resolve(300)
})
MyPromise.all([test1,test2,test3]).then(values=>{
console.log('test1',values)
})
}
function test2(){
const test1=new MyPromise((resolve,reject)=>{
setTimeout(()=>{
resolve(100)
})
})
const test2=new MyPromise((resolve,reject)=>{
reject(200)
})
const test3=new MyPromise((resolve,reject)=>{
resolve(300)
})
MyPromise.all([test1,test2,test3]).then(values=>{
console.log('test2',values)
},reason=>{
console.log('test2',reason)
})
}
test1()
test2()
复制代码
结果:
- 4.race
race
:方法返回一个 promise
,race
接收多个promise一旦某个promise
解决或拒绝,返回的promise
就会解决或拒绝。
实现代码:
//promise race方法
static race(promises){
return new MyPromise((resolve,reject)=>{
try{
// 遍历promises
promises.forEach(promise=>{
//判断promise中的每一项是不是MyPromise的实例
if(promise instanceof MyPromise){
promise.then(res=>{
resolve(res)
},err=>{
//失败的直接reject
reject(err)
})
}else{
resolve(promise)
}
})
}catch (err){
reject(err)
throw new Error(err)
}
})
}
复制代码
测试代码:
function test(){
const test1=new MyPromise((resolve,reject)=>{
setTimeout(()=>{
resolve(100)
},1000)
})
const test2=new MyPromise((resolve,reject)=>{
reject(200)
})
const test3=new MyPromise((resolve,reject)=>{
resolve(300)
})
MyPromise.race([test1,test2,test3]).then(values=>{
console.log('成功',values)
},reason=>{
console.log('失败',reason)
})
}
test()
复制代码
结果:
- 5.allSettled
allSettled
:接收一个Promise
数组,数组中如有非Promise
项,则此项当做成功,把每一个Promise
的结果,集合成数组,返回
实现代码:
// Promise allSettled方法
static allSettled(promises){
//保存结果
let result = []
//记录保存数量
let count = 0
//返回一个Promise
return new MyPromise((resolve,reject)=>{
//保存成功的结果
const save = (value,index,state) => {
//用index保存是为了与promises的顺序一致
result[index]={
value,
state
}
// 记录保存数量
count++
//当保存数量与promises一致时说明所有结果都为成功直接resolve
if(count === promises.length) resolve(result)
}
try{
// 遍历promises
promises.forEach((promise,index)=>{
//判断promise中的每一项是不是MyPromise的实例
if(promise instanceof MyPromise){
promise.then(res=>{
//保存promise的结果
save(res,index,'fulfilled')
},err=>{
save(err,index,'rejected')
})
}else{
//不是MyPromise直接为成功进行保存
save(promise,index,'fulfilled')
}
})
}catch (err){
reject(err)
throw new Error(err)
}
})
}
复制代码
测试以上代码:
function test(){
const test1=new MyPromise((resolve,reject)=>{
setTimeout(()=>{
resolve(100)
},1000)
})
const test2=new MyPromise((resolve,reject)=>{
reject(200)
})
const test3=new MyPromise((resolve,reject)=>{
resolve(300)
})
MyPromise.allSettled([test1,test2,test3]).then(values=>{
console.log('成功',values)
},reason=>{
console.log('失败',reason)
})
}
test()
复制代码
结果:
以上就实现了完整的promsie !!
手写promise源码
附上手写的Promise源码:
class MyPromise{
//函数构造器
constructor(execute){
//初始promise状态
this.state='pending'
//result为保存promise结果值
this.result=null
//用于保存then中的onResolved回调
this.onResolvedCallbacks=[]
//用于保存then中的onRejected回调
this.onRejectedCallbacks=[]
try{
//执行execute(执行器)
execute(this.resolve,this.reject)
}catch (err){
this.reject(err)
}
}
//实现resolve
resolve=(value)=>{
//加判断是因为promise状态只更改一次
if(this.state==='pending'){
//当状态为pending是修改为fulfilled
this.state='fulfilled'
//保存成功promise的结果值
this.result=value
//遍历保存的成功回调并调用再删除
while (this.onResolvedCallbacks.length>0){
this.onResolvedCallbacks.shift()()
}
}
}
//实现reject
reject=(reason)=>{
if(this.state==='pending'){
//当状态为pending是修改为reject
this.state='rejected'
//保存失败promise的结果值
this.result=reason
//遍历保存的成功回调并调用再删除
while (this.onRejectedCallbacks.length>0){
this.onRejectedCallbacks.shift()()
}
}
}
//实现then
then(onResolve,onReject){
//判断onResolve是不是函数,如果不是则直接返回
onResolve = typeof onResolve==="function"?onResolve:value=>value
//判断onReject是不是函数,如果不是则把传进来的参数直接扔出报错
onReject = typeof onReject==="function"?onReject:reason=>{throw reason}
const MyPromise2 = new MyPromise((resolve,reject)=>{
try{
//让then异步执行
setTimeout(()=>{
//状态为fulfilled则执行成功回调
if(this.state==='fulfilled'){
//x获取onResolve的返回值
let x = onResolve(this.result)
//调用ResolvePromise并传入返回值x、resolve、reject与MyPromise2
ResolvePromise(x,resolve,reject,MyPromise2)
}
//状态为rejected则执行失败回调
else if(this.state === 'rejected'){
//x获取onReject的返回值
let x = onReject(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
}
//当状态为pending时则保存onResolve与onReject
else if(this.state === 'pending'){
this.onResolvedCallbacks.push(()=>{
let x = onResolve(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
})
this.onRejectedCallbacks.push(()=>{
let x = onReject(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
})
}
},0)
//ResolvePromise是用来判断onResolve与onReject的返回值并做出处理
const ResolvePromise = (x,resolve,reject,promise2) => {
//如果x等于then的返回值则扔出报错
if(x === promise2){
throw new Error('不能返回自身')
}
//如果x是MyPromise实例,则使用.then方法来获取MyPromise的结果
if(x instanceof MyPromise){
x.then(res=>{
resolve(res)
},err=>{
reject(err)
})
}
//如果不是MyPromise实例则直接resolve
else{
resolve(x)
}
}
}catch (err){
reject(err)
throw new Error(err)
}
})
return MyPromise2
}
//实现catch
catch(onReject){
//判断onReject是不是函数,如果不是则把传进来的参数直接扔出报错
onReject = typeof onReject==="function"?onReject:reason=>{throw reason}
const MyPromise2 = new MyPromise((resolve,reject)=>{
try{
//让then异步执行
setTimeout(()=>{
//状态为rejected则执行失败回调
if(this.state === 'rejected'){
//x获取onReject的返回值
let x = onReject(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
}
//当状态为pending时则保存onResolve与onReject
else if(this.state === 'pending'){
this.onRejectedCallbacks.push(()=>{
let x = onReject(this.result)
ResolvePromise(x,resolve,reject,MyPromise2)
})
}
},0)
//ResolvePromise是用来判断onResolve与onReject的返回值并做出处理
const ResolvePromise = (x,resolve,reject,promise2) => {
//如果x等于then的返回值则扔出报错
if(x === promise2){
throw new Error('不能返回自身')
}
//如果x是MyPromise实例,则使用.then方法来获取MyPromise的结果
if(x instanceof MyPromise){
x.then(res=>{
resolve(res)
},err=>{
reject(err)
})
}
//如果不是MyPromise实例则直接resolve
else{
resolve(x)
}
}
}catch (err){
reject(err)
throw new Error(err)
}
})
return MyPromise2
}
//promise resolve方法
static resolve(value){
return new MyPromise((resolve,reject)=>{
resolve(value)
})
}
//promise reject方法
static reject(reason){
return new MyPromise((resolve,reject)=>{
reject(reason)
})
}
//promise all方法
static all(promises){
//保存成功结果
let success = []
//记录保存数量
let count = 0
//返回一个Promise
return new MyPromise((resolve,reject)=>{
//保存成功的结果
const save = (value,index) => {
//用index保存是为了与promises的顺序一致
success[index]=value
// 记录保存数量
count++
//当保存数量与promises一致时说明所有结果都为成功直接resolve
if(count === promises.length) resolve(success)
}
try{
// 遍历promises
promises.forEach((promise,index)=>{
//判断promise中的每一项是不是MyPromise的实例
if(promise instanceof MyPromise){
promise.then(res=>{
//成功的promise则保存结果
save(res,index)
},err=>{
//失败的直接reject
reject(err)
})
}else{
//不是MyPromise直接为成功进行保存
save(promise,index)
}
})
}catch (err){
reject(err)
throw new Error(err)
}
})
}
//promise race方法
static race(promises){
return new MyPromise((resolve,reject)=>{
try{
// 遍历promises
promises.forEach(promise=>{
//判断promise中的每一项是不是MyPromise的实例
if(promise instanceof MyPromise){
promise.then(res=>{
resolve(res)
},err=>{
//失败的直接reject
reject(err)
})
}else{
resolve(promise)
}
})
}catch (err){
reject(err)
throw new Error(err)
}
})
}
// Promise allSettled方法
static allSettled(promises){
//保存结果
let result = []
//记录保存数量
let count = 0
//返回一个Promise
return new MyPromise((resolve,reject)=>{
//保存成功的结果
const save = (value,index,state) => {
//用index保存是为了与promises的顺序一致
result[index]={
value,
state
}
// 记录保存数量
count++
//当保存数量与promises一致时说明所有结果都为成功直接resolve
if(count === promises.length) resolve(result)
}
try{
// 遍历promises
promises.forEach((promise,index)=>{
//判断promise中的每一项是不是MyPromise的实例
if(promise instanceof MyPromise){
promise.then(res=>{
//保存promise的结果
save(res,index,'fulfilled')
},err=>{
save(err,index,'rejected')
})
}else{
//不是MyPromise直接为成功进行保存
save(promise,index,'fulfilled')
}
})
}catch (err){
reject(err)
throw new Error(err)
}
})
}
}
复制代码