promise的使用
var p1 = new Promise(function(resolve, reject){
resolve(1);
// reject(0);
})
p1.then(data => {
console.log(data)
})
promise核心逻辑
promise核心就是一个class类,这个类需要一个执行器进去立即执行。 另外promise需要三个状态 pending,fulfilled,rejected。
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class myPromise {
constructor(executor){
executor(this.resolve,this.reject)
}
// promise 状态
status = PENDING
// 成功之后的值
value= undefined
// 失败之后的原因
err= undefined
resolve= value=>{
// 如果状态不是等待 阻止程序继续执行
// 将状态改为成功
if(this.status !== PENDING) return
this.status= FULFILLED
// 保存成功的值,then函数要拿到
this.value= value
}
reject= reason=>{
if(this.status !== PENDING) return
this.status= REJECTED
// 保存失败原因
this.err= reason
}
then(successCallback,failCallback){ //接收两个回调函数 成功 失败
if(this.status === FULFILLED){
successCallback(this.value)
}else if(this.status === REJECTED){
failCallback(this.err)
}
}
}
module.exports= myPromise
resolve 和 reject方法在执行的时候各自保存成功的val值和失败的err原因,在之后then方法会用到
在使用promise调用then方法的时候传入了fn,then方法内部会判断promise的状态是fulfilled还是rejected来决定执行的fn是成功回调还是失败回调
当promise状态是pending的时候
let promise= new MyPromise((resolve,reject)=>{
setTimeout(()=>{类型
resolve("成功...")
},5000)
// resolve("成功")
})
当resolve或reject是异步执行的时候,此时promise的status还是pending,我们并不能知道then方法到底需要执行成功回调还是失败回调,所以我们在调用then方法的时候,then(successCallback,failCallback)方法内部需要将这两个回调方法储存起来,需要注意的是,因为then方法支持多次调用,所以储存回调方法的容器需要是一个array类型
// 成功回调
successCallback= []
// 失败回调
failCallback= []
then(successCallback,failCallback){ //接收两个回调函数 成功 失败
if(this.status === FULFILLED){
successCallback(this.value)
}else if(this.status === REJECTED){
failCallback(this.err)
}else{
// 执行器是异步操作时,status还是pending
this.successCallback.push(successCallback),
this.failCallback.push(failCallback)
}
}
之后当resolve或者reject方法被调用的时候,那时promise的status以及重新赋值,我们已经知道了状态,就可以从容器数组中取出需要执行对应的成功回调或者失败回调
resolve= value=>{
// 如果状态不是等待 阻止程序继续执行
// 将状态改为成功
if(this.status !== PENDING) return
this.status= FULFILLED
// 保存成功的值,then函数要拿到
this.value= value
while(this.successCallback.length) this.successCallback.shift()(this.value)
}
reject= reason=>{
if(this.status !== PENDING) return
this.status= REJECTED
// 保存失败原因
this.err= reason
while(this.failCallback.length) this.failCallback.shift()(this.err)
}
详解then的链式调用
上面提到then方法接收两个参数 successCallback和failCallback,两个回调方法,当resolve的时候执行成功回调,reject执行失败回调
但如此还不能达到链式调用的效果,接下来来看看实现链式调用的核心逻辑
- then方法执行结束需要返回一个新的promise对象
- 返回新的promise对象需要接收上一个promise对象返回的结果,也就是需要把
successCallback(this.value)传递给新的promise对象的resolve - 判断上一次promise对象的返回值是普通值还是promise对象,普通值则直接resolve,如果是promise则需要另外判断其返回结果再决定走resolve还是reject
function resolvePromise(x, resolve,reject){
if(x instanceof MyPromise){
// promise对象
x.then(resolve,reject)
}else{
// 普通值
resolve(x)
}
}
定义resolvePromise方法来实现上述第三点,这个方法接收所需返回的新的promise对象,通过instanceof判断这个对象是否继承自myPromise类
在then方法执行时我们new MyPromise得到新的promise
then(successCallback,failCallback){ //接收两个回调函数 成功 失败
// 定义一个新的promise对象实现链式调用
let newPromise= new MyPromise((resolve,reject)=>{
if(this.status === FULFILLED){
let x= successCallback(this.value)
// resolve(x)
resolvePromise(x,resolve,reject)
}else if(this.status === REJECTED){
failCallback(this.err)
}else{
// 执行器是异步操作时,status还是pending
this.successCallback.push(successCallback),
this.failCallback.push(failCallback)
}
})
return newPromise
}