一.Promise的三个状态以及executor执行器
1.1 Promise有三个状态分别时PENDING FULFILLED REJECTED
1.2 Promise接收一个参数executor也就是执行器executor 这个执行器是一个函数 并且接口两个参数 resolve reject这两个也是函数
1.3 由于我们是通过new Promise生成Promise对象 所以因为new内部原理 在new的时候会自动执行constructor这个构造函数,所以我们要在constructor中执行executor这个执行器 在executor函数体内去执行resolve reject方法 将内容传递出去
1.4 我们的then方法也接受两个参数 这两个参数也是函数 这两个函数的作用是根据状态去用指定的函数接收执行器函数块内传过来的内容
1.5 如果executor函数体内抛出的是异常我们需要利用try catch进行捕获 并且reject出去
const MyPromise = require('./MyPromise')
let promise = new Promise((resolve,reject)=>{
resolve('value')
*
*
})
promise.then((value)=>{
console.log(value)
},(reason)=>{
console.log(reason)
})
const PENDING = 'PENDING',
FULFILLED = 'FULFILLED',
REJECTED = 'REJECTED';
class MyPromise{
constructor(executor){ *
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
const resolve = (value)=>{
if(this.status === PENDING){
this.status = FULFILLED;
this.value = value
}
}
const reject = (reason)=>{
if(this.status === PENDING){
this.status = REJECTED
this.reason = reason
}
}
try{
executor(resolve,reject) *
}catch(e){
reject(e)
}
then(onFulfilled,onRejected*){ *
if(this.status === FULFILLED){
onFulfilled(this.value)
}
if(this.status === REJECTED){
onRejected(this.reason)
}
}
}
module.exports = MyPromise
二.发布者订阅者处理异步Promise
当我们Promise产生异步的resolve或者reject的时候我们应该如何处理
2.1 当我们new Promise的时候 执行器executor会自动执行 函数体内的resolve reject throw等也会执行并且改变Promise当前的状态 如果存在的话 但是当resolve reject异步的时候 executor自动执行的时候 并没有能够立即去执行resolve reject也就意味着并不会改变当前Promise的状态 所以我们就需要处理状态为PENDING的情况
2.2 当我们执行then方法 发现Promise的状态还是PENDING的时候我们就无法立即执行then中的两个函数 我们需要将then方法等待Promise状态改变后执行的两个函数订阅起来
2.3 等到延时到达的时候 executor执行器函数体内的resolve reject方法被执行的时候 我们再去发布订阅的函数
const MyPromise = require('./MyPromise')
let promise = new MyPromise((resolve,reject)=>{
setTimeout(() => {
resolve('Success')
}, 2000);
})
promise.then((value)=>{
console.log(value)
},(reason)=>{
console.log(reason)
})
const PENDING = 'PENDING',
FULFILLED = 'FULFILLED',
REJECTED = 'REJECTED';
class MyPromise{
constructor(executor){
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
const resolve = (value)=>{
if(this.status === PENDING){
this.status = FULFILLED;
this.value = value
this.onFulfilledCallbacks.forEach(fn=>fn())
}
}
const reject = (reason)=>{
if(this.status === PENDING){
this.status = REJECTED
this.reason = reason
this.onRejectedCallbacks.forEach(fn=>fn())
}
}
try{
executor(resolve,reject)
}catch(e){
reject(e)
}
}
then(onFulfilled,onRejected){
if(this.status === FULFILLED){
onFulfilled(this.value)
}
if(this.status === REJECTED){
onRejected(this.reason)
}
if(this.status === PENDING){ *
*
*
this.onFulfilledCallbacks.push(()=>{
onFulfilled(this.value)
})
this.onRejectedCallbacks.push(()=>{
onRejected(this.reason)
})
}
}
}
module.exports = MyPromise
三.Promise的链式回调以及then的处理
3.1 then方法其实返回的仍然是一个Promise对象,只有这样我们才能继续的链式调用.then.then下去否则是不可能的,所以我们需要在then方法内包裹一层Promise并return出去以便后续的链式调用
3.2 争对then方法内部onFulfilled或者onRejected方法执行后获得的x我们需要判断其的形式
3.2.1 如果x是当前Promise对象
3.2.2 如果x是一个普通的值
3.2.3 如果x是Promise语法糖
3.2.4 如果x是一个新的Promise
3.2.5 如果函数内部抛出错误
3.3 确保当3.2.4的情况下如果resolve并且reject同时有的时候我们只运行一个
const MyPromise = require('./MyPromise')
let promise1 = new MyPromise((resolve,reject)=>{
resolve('promise1')
})
let promise2 = promise1.then((value)=>{
return new MyPromise((resolve,reject)=>{
resolve(value + '->then->promise2')
reject('溜了溜了')
})
})
.then((value)=>{
console.log(value)
})
const PENDING = 'PENDING',
FULFILLED = 'FULFILLED',
REJECTED = 'REJECTED';
class MyPromise{
constructor(executor){
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
const resolve = (value)=>{
if(this.status === PENDING){
this.status = FULFILLED;
this.value = value
this.onFulfilledCallbacks.forEach(fn=>fn())
}
}
const reject = (reason)=>{
if(this.status === PENDING){
this.status = REJECTED
this.reason = reason
this.onRejectedCallbacks.forEach(fn=>fn())
}
}
try{
executor(resolve,reject)
}catch(e){
reject(e)
}
}
then(onFulfilled,onRejected){
let promise2 = new MyPromise((resolve,reject)=>{
if(this.status === FULFILLED){
setTimeout(()=>{
try{
let x = onFulfilled(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
}
if(this.status === REJECTED){
setTimeout(()=>{
try{
let x = onRejected(this.reason)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
}
if(this.status === PENDING){
this.onFulfilledCallbacks.push(()=>{
try{
let x = onFulfilled(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
this.onRejectedCallbacks.push(()=>{
try{
let x = onRejected(this.reason)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
}
})
return promise2
}
}
function resolvePromise(promise2,x,resolve,reject){
if(promise2 == x){
reject(new TypeError('CHAINING CYCLE'))
}
let called = false;
if((typeof x === 'object' && x!==null) || typeof x === 'function'){
try{
let then = x.then
if(typeof then === 'function'){
then.call(x,(y)=>{
if(called) return
called = true;
resolve(y)
},(r)=>{
if(called) return
called = true;
reject(r)
})
}else{
resolve(x)
}
}catch(e){
if(called) return
called = true;
reject(e)
}
}else{
resolve(x)
}
}
module.exports = MyPromise
四.Promise多层嵌套、链式调用与catch方法实现(Promise源码最终版)
4.1 当我们去深层次抛出Promise的时候 我们需要递归的去处理这些Promise
4.2 对于.then().then().then()这种没有传递参数的then我们需要去给定两个函数参数来穿透到最后
4.3 catch本质上就是一个then方法 但是它只抛出错误 所以也就是then(null,onRejected)这种形式 只使用第二个函数参数去抛出结果
const MyPromise = require('./MyPromise')
let promise1 = new MyPromise((resolve,reject)=>{
resolve('promise1')
})
let promise2 = promise1.then((value)=>{
return new MyPromise((resolve,reject)=>{
setTimeout(()=>{
resolve(new MyPromise((resolve,reject)=>{
resolve(new MyPromise((resolve)=>{
resolve('递归')
}))
}))
},2000)
})
})
promise2.then().then().then().then().then((value)=>{
throw new Error('Error')
},(reason)=>{
console.log(reason)
}).catch((e)=>{
console.log(e)
})
const PENDING = 'PENDING',
FULFILLED = 'FULFILLED',
REJECTED = 'REJECTED';
class MyPromise{
constructor(executor){
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
const resolve = (value)=>{
if(this.status === PENDING){
this.status = FULFILLED;
this.value = value
this.onFulfilledCallbacks.forEach(fn=>fn())
}
}
const reject = (reason)=>{
if(this.status === PENDING){
this.status = REJECTED
this.reason = reason
this.onRejectedCallbacks.forEach(fn=>fn())
}
}
try{
executor(resolve,reject)
}catch(e){
reject(e)
}
}
then(onFulfilled,onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value=>value;
onRejected = typeof onRejected === 'function' ? onRejected : reason=>{throw reason}
let promise2 = new MyPromise((resolve,reject)=>{
if(this.status === FULFILLED){
setTimeout(()=>{
try{
let x = onFulfilled(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
}
if(this.status === REJECTED){
setTimeout(()=>{
try{
let x = onRejected(this.reason)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
}
if(this.status === PENDING){
this.onFulfilledCallbacks.push(()=>{
try{
let x = onFulfilled(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
this.onRejectedCallbacks.push(()=>{
try{
let x = onRejected(this.reason)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
}
})
return promise2
}
catch(errorCallback){
return this.then(null,errorCallback)
}
}
function resolvePromise(promise2,x,resolve,reject){
if(promise2 == x){
reject(new TypeError('CHAINING CYCLE'))
}
let called = false;
if((typeof x === 'object' && x!==null) || typeof x === 'function'){
try{
let then = x.then
if(typeof then === 'function'){
then.call(x,(y)=>{
if(called) return
called = true;
resolvePromise(promise2,y,resolve,reject)
},(r)=>{
if(called) return
called = true;
reject(r)
})
}else{
resolve(x)
}
}catch(e){
if(called) return
called = true;
reject(e)
}
}else{
resolve(x)
}
}
module.exports = MyPromise