理解Promise原理,手写一个MyPromise。
核心功能
根据Promise,推断MyPromise
1 2 3 4 5 6 7 8 9 10 11 12 13
| new Promise((resolve,reject)=>{ if(xxx){ resolve('resolve') }else{ reject('reject') } }).then(res=>{ },error=>{ }).catch(error=>{ })
|
根据上述代码,我们可以推断
- Promise是一个类,使用类时需要传递一个执行器,并且执行器立即执行
1 2 3 4 5 6
| class MyPromise{ constructor(exector){ exector(this.resolve,this.reject) } }
|
Promise有三种状态:等待(pending)、成功(fulfilled)、失败(rejected)
状态变化: pending –> fulfilled.
pending –> rejected
默认状态为pending
1 2 3 4 5 6 7 8 9 10 11 12 13
|
const FULFILLED ='fulfilled'; const REJECTED ='rejected'; const PENDING ='pending';
class MyPromise{ constructor(exector){ exector(this.resolve,this.reject) } status = PENDING; }
|
resolve,reject是用来更改状态的
resolve –> fulfilled
reject —> rejected
状态一旦变化,便不可更改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
const FULFILLED ='fulfilled'; const REJECTED ='rejected'; const PENDING ='pending';
class MyPromise{ constructor(exector){ exector(this.resolve,this.reject) } status = PENDING; resolve = (value)=>{ if(this.status !== PENDING){ return; } this.status = FULFILLED } reject = (reason)=>{ if(this.status !== PENDING){ return; } this.status = REJECTED } }
|
then方法内部判断状态,若状态为成功,调用成功对应的回调函数,若状态为失败,调用失败对应的回调函数。
then方法应该是被定义在原型对象中的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
const FULFILLED ='fulfilled'; const REJECTED ='rejected'; const PENDING ='pending';
class MyPromise{ constructor(exector){ exector(this.resolve,this.reject) } status = PENDING;
resolve = (value)=>{ if(this.status !== PENDING){ return; } this.status = FULFILLED } reject = (reason)=>{ if(this.status !== PENDING){ return; } this.status = REJECTED } then(successCallback,failCallback){ if(this.status === FULFILLED){ successCallback(this.value) }else if(this.status === REJECTED){ failCallback(this.reason) }else{ } } }
|
then成功回调有一个参数,表示成功之后值。失败回调有一个参数,表示失败之后的原因。
在resolve和reject中存储值和原因,便于在then方法中使用,所以要在实例中定义变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
const FULFILLED='fulfilled'; const REJECTED='rejected'; const PENDING='pending';
class MyPromise{ constructor(executor){ executor(this.resolve,this.reject) } status = PENDING; value=undefined reason= undefined
resolve = (value)=>{ if(this.status !== PENDING){ return; } this.status = FULFILLED
this.value = value } reject = (reason)=>{ if(this.status !== PENDING){ return; } this.status = REJECTED
this.reason = reason }
then(successCallback,failCallback){ if(this.status === FULFILLED){ successCallback(this.value) }else if(this.status === REJECTED){ failCallback(this.reason) }else{ } } }
module.exports = MyPromise
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| const myPromise = require('./myPromise')
new myPromise((resolve,reject)=>{ resolve('success') reject('reason') }).then(res=>{ console.log(res) },error=>{ console.log(error) })
|
实现MyPromise异步
Promise中,then方法是在执行器执行完毕之后执行的。但前面我们的基本原理代码,在执行器中有异步函数时,then方法中状态处于pending状态,需要进行特殊处理。
then方法中需要将成功回调和失败回调存储起来,便于状态发生变化时调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
|
const FULFILLED='fulfilled'; const REJECTED='rejected'; const PENDING='pending';
class MyPromise{ constructor(executor){ executor(this.resolve,this.reject) } status = PENDING; value=undefined reason= undefined
successCallback = undefined
failCallback = undefined
resolve = (value)=>{ if(this.status !== PENDING){ return; } this.status = FULFILLED
this.value = value
this.successCallback && this.successCallback(value) } reject = (reason)=>{ if(this.status !== PENDING){ return; } this.status = REJECTED
this.reason = reason
this.failCallback && this.failCallback(reason) }
then(successCallback,failCallback){ if(this.status === FULFILLED){ successCallback(this.value) }else if(this.status === REJECTED){ failCallback(this.reason) }else{ this.successCallback = successCallback this.failCallback = failCallback } } }
module.exports = MyPromise
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const myPromise = require('./myPromise')
new myPromise((resolve,reject)=>{ setTimeout(()=>{ resolve('success') reject('reason') },2000) }).then(res=>{ console.log(res) },error=>{ console.log(error) })
|
then方法多次调用
当then方法被多次调用的时候,每个then方法都要分别执行。
同步时直接依次盗用then方法中对应的回调函数
异步时,依次存储then方法中的回调函数,然后在状态发生变化时调用。
成功回调和失败回调的函数存储在数组中,then方法中,状态为status时,push回调函数到数组中,在resolve和reject执行时,再执行回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
const FULFILLED='fulfilled'; const REJECTED='rejected'; const PENDING='pending';
class MyPromise{ constructor(executor){ executor(this.resolve,this.reject) } status = PENDING; value=undefined reason= undefined
successCallback = []
failCallback = []
resolve = (value)=>{ if(this.status !== PENDING){ return; } this.status = FULFILLED
this.value = value
while(this.successCallback.length){ this.successCallback.shift()(value) } } reject = (reason)=>{ if(this.status !== PENDING){ return; } this.status = REJECTED
this.reason = reason
while(this.successCallback.length){ this.successCallback.shift()(reason) } }
then(successCallback,failCallback){ if(this.status === FULFILLED){ successCallback(this.value) }else if(this.status === REJECTED){ failCallback(this.reason) }else{ this.successCallback.push(successCallback) this.failCallback.push(failCallback) } } }
module.exports = MyPromise
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const myPromise = require('./myPromise') let promise = new myPromise((resolve,reject)=>{ setTimeout(()=>{ resolve('success') reject('reason') },2000) }) promise.then(res=>{ console.log(res) },error=>{ console.log(error) }) promise.then(res=>{ console.log(res) },error=>{ console.log(error) })
|
then方法链式调用
then方法链式调用,下一个then会接收上一个then方法的返回值。
而then方法是promise类中的方法,所以,then方法的返回值是Promise。
1 2 3 4 5 6 7 8 9 10 11
| class MyPromise{ then(succcessCallBack,failCallback){ return new MyPromise((resolve,reject)=>{
}) } }
|
then方法中,下一个then方法可以拿到上一个then方法中回调函数执行的值,故而,需要在上一个then方法中执行resolve或reject方法,并将回调函数的结果传递给下一个then方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
class MyPromise{ then(successCallback,failCallback){ return new MyPromise((resolve,reject)=>{ if(this.status == FULFILLED){ let x = successCallback(this.value) resolve(x) }else if(this.status == REJECTED){ let reason = failCallback(this.reason) reject(reason) }else{ this.successCallback.push(successCallback) this.failCallback.push(failCallback) } }) } }
|
但是若回调函数的返回值为Promise对象,则需要拿到promise对象的的返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| class MyPromise{ resove = (value)=>{ if(this.status !== PENDING){ return } this.status = FULFILLED this.value = value while(this.successCallback.length){ this.successCallback.shift()() } } reject = (reason)=>{ if(this.status !== PENDING){ return } this.status = REJECTED this.reason = reason while(this.failCallback.length){ this.failCallback.shift()() } } then(successCallback,failCallback){ return new MyPromise((resolve,reject)=>{ if(this.status == FULFILLED){ let x = successCallback(this.value) if(x instanceof MyPromise){ x.then(value=>resolve(value),reason=>reject(reason)) }else{ resolve(x) } }else if(this.status == REJECTED){ let x = failCallback(this.reason) if(x instanceof MyPromise){ x.then(value=>resolve(value),reason=>reject(reason)) }else{ reject(x) } }else{ this.successCallback.push(()=>{ let x = successCallback(this.value) if(x instanceof MyPromise){ x.then(value=>resolve(value),reason=>reject(reason)) }else{ resolve(x) } }) this.failCallback.push(()=>{ let x = failCallback(this.reason) if(x instanceof MyPromise){ x.then(value=>resolve(value),reason=>reject(reason)) }else{ reject(x) } }) } }) } }
|
进一步优化,提取resolvePromise
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| class MyPromise{ resove = (value)=>{ if(this.status !== PENDING){ return } this.status = FULFILLED this.value = value while(this.successCallback.length){ this.successCallback.shift()() } } reject = (reason)=>{ if(this.status !== PENDING){ return } this.status = REJECTED this.reason = reason while(this.failCallback.length){ this.failCallback.shift()() } } then(successCallback,failCallback){ return new MyPromise((resolve,reject)=>{ if(this.status == FULFILLED){ let x = successCallback(this.value) resolvePromise(x,resolve,reject) }else if(this.status == REJECTED){ let x = failCallback(this.reason) resolvePromise(x,resolve,reject) }else{ this.successCallback.push(()=>{ let x = successCallback(this.value) resolvePromise(x,resolve,reject) }) this.failCallback.push(()=>{ let x = failCallback(this.reason) resolvePromise(x,resolve,reject) }) } }) } }
function resolvePromise(x,resolve,reject){ if(x instanceof MyPromise){ x.then(value=>resolve(value),reason=>reject(reason)) }else{ resolve(x) } }
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const MyPromise = require('./myPromise')
let promise = new MyPromise((resolve,reject)=>{ resolve('success') reject('reason') })
function other(){ return new MyPromise((resolve,reject)=>{ resolve('other') }) }
promise.then(res=>{ console.log(res) return other(); },error=>{ console.log(error) }).then(res=>{ console.log(res) },error=>{ console.log(error) })
|
then方法参数为可选参数
在实际使用Promise的时候,会有这种情况
1 2 3 4 5 6 7
| let promise = new Promise((resolve,reject)=>{ resolve('成功') }) promise.then().then().then(res=>{ console.log(res) })
|
这个时候,前两then方法中没有回调函数的参数,但是,promise的fulfilled状态是一值保持到有回调函数参数的then方法中执行回调的,所以我们需要将promise的状态一只传递给后面的then方法
相当于
1 2 3 4 5 6 7 8 9
| let promise = new Promise((resolve,reject)=>{ resolve('成功') }) promise.then(res=>res) .then(res=>res) .then(res=>{ console.log(res) })
|
因此,我们只需要在then方法中补充一个函数就可以了
1 2 3 4 5 6 7 8 9 10
| class MyPromise{ then(successCallback,failCallback){ successCallback = successCallback ? successCallback : value => value failCallback = failCallback ? failCallback : reason => {throw reason} } }
|
处理自己返回自己的异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
let promise = new Promise((resolve,reject)=>{ resolve('success') reject('reason') }) let p1 = promise.then(value=>{ console.log(value) return p1; })
p1.then(value=>{ console.log(value) },reason=>{ console.log(reason) })
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| class MyPromise{ then(successCallback,failCallback){ let promise2 = new MyPromise((resolve,reject)=>{ if(this.status == FULFILLED){ setTimeout(()=>{ let x = successCallback(this.value) resolvePromise(promise2,x,resolve,reject) },0) }else if(this.status == REJECTED){ setTimeout(()=>{ let x = failCallback(this.reason) resolvePromise(promise2,x,resolve,reject) },0) }else{ this.successCallback.push(()=>{ setTimeout(()=>{ let x = successCallback(this.value) resolvePromise(promise2,x,resolve,reject) },0) }) this.failCallback.push(()=>{ setTimeout(()=>{ let x = failCallback(this.reason) resolvePromise(promise2,x,resolve,reject) },0) }) } }) return promise2 } }
function resolvePromise(promise2,x,resolve,reject){ if(promise2===x){ return reject(new TypeError('Chaining cycle detected for promise #<Promise>')) } if(x instanceof MyPromise){ x.then(value=>resolve(value),reason=>reject(reason)) }else{ resolve(x) } }
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const MyPromise = require('./myPromise')
let promise = new MyPromise((resolve,reject)=>{ resolve('success') reject('reason') }) let p1 = promise.then(value=>{ console.log(value) return p1; })
p1.then(value=>{ console.log(value) },reason=>{ console.log(reason) })
|
异常处理
- Promise执行器中异常捕获抛出
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
class MyPromise{ constructor(executor){ try{ executor(this.resolve,this.reject) }catch(e){ this.reject(e) } } }
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12
| const MyPromise = require('./myPromise')
let promise = new MyPromise((resolve,reject)=>{ throw new Error('execuor error') }) promise.then(value=>{ console.log(value) },reason=>{ console.log(reason.message) })
|
- then方法中的回调函数在执行过程中发生错误,在下一个then方法中要将异常捕获抛出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
|
class MyPromise{ then(successCallback,failCallback){ let promise2 = new MyPromise((resolve,reject)=>{ if(this.status == FULFILLED){ setTimeout(()=>{ try{ let x = successCallback(this.value) resolvePromise(promise2,x,resolve,reject) }catch(e){ reject(e) } },0) }else if(this.status == REJECTED){ setTimeout(()=>{ try{ let x = failCallback(this.reason) resolvePromise(promise2,x,resolve,reject) }catch(e){ reject(e) } },0) }else{ this.successCallback.push(()=>{ setTimeout(()=>{ try{ let x = successCallback(this.value) resolvePromise(promise2,x,resolve,reject) }catch(e){ reject(e) } },0) }) this.failCallback.push(()=>{ setTimeout(()=>{ try{ let x = failCallback(this.reason) resolvePromise(promise2,x,resolve,reject) }catch(e){ reject(e) } },0) }) } }) return promise2 } }
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const MyPromise = require('./myPromise')
let promise = new MyPromise((resolve,reject)=>{ resolve('成功') }) promise.then(value=>{ console.log(value) throw new Error('then error') },reason=>{ console.log(reason.message) }).then(value=>{ console.log(value) },reason=>{ console.log(reason.message) })
|
核心功能代码汇总
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
| const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; const PENDING = 'pending';
class MyPromise{ constructor(executor){ try{ executor(this.resolve,this.reject) }catch(e){ this.reject(e) } } status = PENDING; value = undefined; reason = undefined; successCallback = []; failCallback = [];
resolve = (value)=>{ if(this.status !== PENDING){ return } this.status = FULFILLED; this.value = value; while(this.successCallback.length){ this.successCallback.shift()() } }
reject = (reason)=>{ if(this.status !== PENDING){ return } this.status = REJECTED; this.reason = reason; while(this.failCallback.length){ this.failCallback.shift()() } }
then(successCallback,failCallback){ successCallback = successCallback ? successCallback : value=>value failCallback = failCallback ? failCallback : reason=>{throw reason} let promise2 = new MyPromise((resolve,reject)=>{ if(this.status == FULFILLED){ setTimeout(()=>{ try{ let x= successCallback(this.value) resolvePromise(promise2,x,resolve,reject) }catch(e){ reject(e) } },0) }else if(this.status == REJECTED){ setTimeout(()=>{ try{ let x= failCallback(this.reason) resolvePromise(promise2,x,resolve,reject) }catch(e){ reject(e) } },0) }else{ this.successCallback.push(()=>{ setTimeout(()=>{ try{ let x= successCallback(this.value) resolvePromise(promise2,x,resolve,reject) }catch(e){ reject(e) } },0) }) this.failCallback.push(()=>{ setTimeout(()=>{ try{ let x= failCallback(this.reason) resolvePromise(promise2,x,resolve,reject) }catch(e){ reject(e) } },0) }) } }) return promise2 } }
function resolvePromise(promise2,x,resolve,reject){ if(promise2 === x){ return reject(new TypeError('Chaining cycle detected for promise #<Promise>')) } if(x instanceof MyPromise){ x.then((value)=>resolve(value),(reason)=>reject(reason)) }else{ resolve(x) } }
module.exports = MyPromise
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const MyPromise = require('./myPromise')
let promise = new MyPromise((resolve,reject)=>{ setTimeout(()=>{ reject('fail') },2000) }) promise.then().then().then(value=>{ console.log(value) return new MyPromise((resolve,reject)=>{ reject('resolve') }) },reason=>{ console.log(reason) return new MyPromise((resolve,reject)=>{ reject('reject') }) }).then(value=>{ console.log(value) },reason=>{ console.log(reason) })
|
其他方法
all方法
all方法是用来解决异步并发问题的,它允许我们按照异步代码调用的顺序得到异步代码执行的结果。
接收一个数组作为参数,数组中可以是普通值和Promise对象,数组中值得顺序即为得到的结果的顺序。
返回值是一个Promise对象,可以链式调用then方法。
若all的参数中,所有Promise对象的结果都是成功的,则all结果也是成功的。
若all的参数中,有Promise对象的结果是失败的,则all结果也是失败的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function p1(){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve('p1') },2000) }) } function p2(){ return new Promise((resolve,reject)=>{ resolve('p2') }) } Promise.all(['a','b',p1(),p2(),'c']) .then(res=>{ console.log(res) })
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class MyPromise{ static all(array){ let result = [] let index = 0 return new MyPromise((resolve,reject)=>{ function addData(key,value){ result[key] = value index++; if(index === array.length){ resolve(result) } } for(let i = 0; i<array.length;i++){ let current = array[i] if(current instanceof MyPromise){ current.then(value=>{ addData(i,value) },reason=>{ reject(reason) }) }else{ addData(i,current) } } }) } }
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const MyPromise = require('./myPromise')
function p1(){ return new MyPromise((resolve,reject)=>{ setTimeout(()=>{ resolve('p1') },2000) }) } function p2(){ return new MyPromise((resolve,reject)=>{ resolve('p2') }) } MyPromise.all(['a','b',p1(),p2(),'c']) .then(res=>{ console.log(res) })
|
resolve方法
将给定的值转换为Promise对象。所以,resolve方法的返回值是一个Promise对象。
1 2 3 4 5 6 7 8 9 10 11 12
| function p1(){ return new Promise((resolve,reject)=>{ resolve('hello') }) } Promise.resolve(10).then(res=>{ console.log(res) }) Promise.resolve(p1()).then(res=>{ console.log(res) })
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class MyPromise{ static resolve(value){ if(value instanceof MyPromise){ return value }else{ return new MyPromise(resolve=>{ resolve(value) }) } } }
|
finally方法
无论当前Promise对象最终的状态是成功的还是失败的,finally方法中的函数都会被执行一次。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class MyPromise{ finally(callback){ return this.then((value)=>{ return MyPromise.resolve(callback()).then(()=>value) },(reason)=>{ return MyPromise.resolve(callback()).then(()=>{throw reason}) }) } }
|
catch方法
用来处理Promise对象失败的情况
1 2 3 4 5 6 7 8
| class MyPromise{ catch(failCallback){ return this.then(undefined,failCallback) } }
|