美文网首页
promise的基本用法以及实现原理

promise的基本用法以及实现原理

作者: 仔崽06 | 来源:发表于2020-10-11 18:50 被阅读0次

1.promise是什么?

promise是异步编程的一种解决方案,解决多个异步方法串行的问题,比如回调地狱等.所谓的promise,简单地说就是一个容器,里面保存着某个未来才会结束的事件,从语法说promise是一个对象,从他可以获取异步操作的消息。promise提供统一的api,各种操作都可以用相同的方法进行处理.

2.promise的特点

1.对象的状态不收外界影响,promise对象代表一个异步操作,有三种状态pending(进行中),fulfilled(已成功)和rejected(已失败)。只有一步的操作结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2.一旦状态改变,就不会在编,任何时候都可以得到这个结果。promise对象的状态改变只有两种可能:从pending变为fulfilled或从pending变为rehected.

2.基本用法

ES6规定,promise对象是一个构造函数,用来生成Promise实例。
promise默认传入exectutor执行器 立即执行。
promise提供两个方法reslove和reject.
promise实例生成后,可以用then方法分别指定resloved状态和rejected状态的回调函数.

let p1=new Promise((reslove,reject)=>{
    if(true){
        reslove('成功')
    }else{
        reject('失败')
    }
})
p1.then((data)=>{
    //成功的回调
    console.log(data)
},(err)=>{
    //失败的回调
    console.log(err)
})

基本用法的简单实现

//1.exectutor执行器 立即执行
//三种状态默认是等待态 resolve成功态  reject失败态

const PENDING='PENDING'
const RESOLVE='RESOLVE'
const REJECT='REJECT'
class Promise{
    constructor(exectutor){
        //成功状态的取值
        this.success_val=undefined;
        //失败状态的取值
        this.error_val=undefined;
        //状态
        this.status=PENDING;
        //成功回调
        let resolve=(val)=>{
            //判断如果是等待态 将状态赋值 不能再修改状态
            if(this.status===PENDING){
                this.success_val=val;
                this.status=RESOLVE;
            }
        }
        //失败回调
        let reject=(err)=>{
            //同上
            if(this.status===PENDING){
                this.error_val=err;
                this.status=REJECT
            }
        }
        try{
           exectutor(resolve,reject)
        }catch(err){
            //如果是 throw err直接手动调用reject
           reject(err)
        }
    }
    then(successFn,errFn){
        //then会传入两个回调函数 一个成功一个失败
        //如果状态是成功态 successFn执行
        if(this.status===RESOLVE){
            successFn(this.success_val)
        }
        //反之
        if(this.status===REJECT){
            errFn(this.error_val)
        }
    }
}

promise里面setTimeout几秒后resolve或者reject结果,异步操作,这时候需要用到发布订阅模式.

const Promise=require('./promise.js')
let p1=new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('成功')
    },3000)
})
p1.then((data)=>{
    console.log(data)
},(err)=>{
    console.log(err)
})
//此时promise应该是等待态
const PENDING='PENDING'
const RESOLVE='RESOLVE'
const REJECT='REJECT'
class Promise{
    constructor(exectutor){
        //成功状态的取值
        this.success_val=undefined;
        //失败状态的取值
        this.error_val=undefined;
        //状态
        this.status=PENDING;
        //成功数组里存放执行器
        this.success_arr=[];
        //失败数组里存放执行器
        this.err_arr=[];
        //成功回调
        let resolve=(val)=>{
            //判断如果是等待态 将状态赋值 不能再修改状态
            if(this.status===PENDING){
                this.success_val=val;
                this.status=RESOLVE;
                //promise 成功态后只需依次执行this.success里的函数即可
                this.success_arr.forEach(fn=>{
                    fn()
                })
            }
        }
        //失败回调
        let reject=(err)=>{
            //同上
            if(this.status===PENDING){
                this.error_val=err;
                this.status=REJECT
                this.err_arr.forEach(fn=>{
                    fn()
                })
            }
        }
        try{
           exectutor(resolve,reject)
        }catch(err){
            //如果是 throw err直接手动调用reject
           reject(err)
        }
    }
    then(successFn,errFn){
        //then会传入两个回调函数 一个成功一个失败
        //如果状态是成功态 successFn执行
        if(this.status===RESOLVE){
            successFn(this.success_val)
        }
        //反之
        if(this.status===REJECT){
            errFn(this.error_val)
        }
        //有异步操作这时promise的状态为pedding
        if(this.status===PENDING){
            this.success_arr.push(()=>{
                //添加一个函数代码可拓展 增加别的逻辑 successFn执行的时候 当前状态已改为成功态 this.success的值已经改变
                successFn(this.success_val)
            })
            this.err_arr.push(()=>{
                errFn(this.error_val)
            })
        }
    }
}

module.exports=Promise;

promise中的链式调用类似于jquery的链式调用,不同的是jquery返回的是this,promise返回的是一个新的promise。

  1. then放方法中(成功或者失败)只要不是返回一个promise,都会将结果返回到下一个then中成功的回调函数.
let p1=new Promise((resolve,reject)=>{
    resolve('成功')
})
p1.then((data)=>{
    console.log(data) //成功
    return 2
},(err)=>{
    console.log(err)
}).then((data)=>{
    console.log(data) //2
},(err)=>{
    console.log(err)
})
let p1=new Promise((resolve,reject)=>{
    reject('失败')
})
p1.then((data)=>{
    return 2
},(err)=>{
    return err
}).then((data)=>{
    console.log('success',data)  //success 失败
},(err)=>{
    console.log('err',err)
})
  1. 如果then方法中抛出异常(throw new Error),会将结果返回到下一个then的失败的回调函数.
let p1=new Promise((resolve,reject)=>{
    resolve('成功')
})
p1.then((data)=>{
    throw new Error('成功回调里 抛出异常')
},(err)=>{
    return err
}).then((data)=>{
    console.log('success',data) 
},(err)=>{
    console.log('err',err) //err Error: 成功回调里 抛出异常
})
  1. 如果返回一个promise,会将这个promise的返回结果,作为下一次then里成功或者失败.
//新promise成功返回
let p1=new Promise((resolve,reject)=>{
    resolve('成功')
})
p1.then((data)=>{
    return new Promise((resolve,reject)=>{
        resolve('新promise成功')
    })
},(err)=>{
    return err
}).then((data)=>{
    console.log('success',data)  //success 新promise成功
},(err)=>{
    console.log('err',err)
})

//新promise失败返回
let p1=new Promise((resolve,reject)=>{
    resolve('成功')
})
p1.then((data)=>{
    return new Promise((resolve,reject)=>{
        reject('新promise失败')  //throw new Error('新promise失败') 同理
    })
},(err)=>{
    return err
}).then((data)=>{
    console.log('success',data)  
},(err)=>{
    console.log('err',err) //err 新promise失败
})
  1. catch错误捕获,先找距离自己近的如果没有错误捕获,会找到最终的catch方法.如果catch返回一个普通值,会将catch结果返回到下一次then的成功回调中。
let p1=new Promise((resolve,reject)=>{
    resolve('成功')
})
p1.then((data)=>{
    return new Promise((resolve,reject)=>{
       reject('新promise失败')
    })
},(err)=>{
    return err
}).then((data)=>{
    console.log('success',data)  
},(err)=>{
    console.log('err',err) //err 新promise失败
}).catch(err=>{
    console.log('catch err',err) //会找最近的 err回调 如果前面定义了err回调 不会走catch错误被捕获
})


//前面没有错误捕获会走到catch方法
let p1=new Promise((resolve,reject)=>{
    resolve('成功')
})
p1.then((data)=>{
    return new Promise((resolve,reject)=>{
       reject('新promise失败')
    })
},(err)=>{
    return err
}).then((data)=>{
    console.log('success',data)  
}).catch(err=>{
    console.log('catch err',err)  //catch err 新promise失败
})

//如果catch返回一个普通值,会将catch结果返回到下一次then的成功回调中
let p1=new Promise((resolve,reject)=>{
    resolve('成功')
})
p1.then((data)=>{
    return new Promise((resolve,reject)=>{
       reject('新promise失败')
    })
},(err)=>{
    return err
}).then((data)=>{
    console.log('success',data)  
}).catch(err=>{
    console.log('catch err',err)
    return err
}).then(data=>{
    console.log('catch success',data) //catch success 新promise失败
})

基于以上特点实现一个完整的promise

const PENDING='PENDING'
const RESOLVE='RESOLVE'
const REJECT='REJECT'
function resolvePromise(promise2,x,resolve,reject){
    //循环引用报错 是同一个对象
    if(promise2===x){
        return reject(new TypeError('Chaining cycle detected for promise'));
    }
    //防止多次调用
    let called;
    //判读then的返回结果是普通值还是promise
    if(typeof x!==null&&(typeof x==='function' || typeof x==='object')){
        try{
            let then=x.then;
            //如果是promise 
            if(typeof then==='function'){
                //成功的回调函数
                 then.call(x,data=>{
                    if(called) return;
                    called=true;
                    //如果返回的还是promise 继续解析,递归调用
                    resolvePromise(promise2,data,resolve,reject)
                },err=>{
                    if(called) return;
                    called=true;
                    reject(err)
                })
            }else{
                //如果是对象 
                resolve(x)
            }
        }catch(err){
            //如果then抛出异常直接调用reject
            if(called) return;
            called=true;
            reject(err)
        }
    }else{
        //普通值直接返回x
        resolve(x)
    }
}
class Promise{
    constructor(exectutor){
        //成功状态的取值
        this.success_val=undefined;
        //失败状态的取值
        this.error_val=undefined;
        //状态
        this.status=PENDING;
        //成功数组里存放执行器
        this.success_arr=[];
        //失败数组里存放执行器
        this.err_arr=[];
        //成功回调
        let resolve=(val)=>{
            //判断如果是等待态 将状态赋值 不能再修改状态
            if(this.status===PENDING){
                this.success_val=val;
                this.status=RESOLVE;
                //promise 成功态后只需依次执行this.success里的函数即可
                this.success_arr.forEach(fn=>{
                    fn()
                })
            }
        }
        //失败回调
        let reject=(err)=>{
            //同上
            if(this.status===PENDING){
                this.error_val=err;
                this.status=REJECT
                this.err_arr.forEach(fn=>{
                    fn()
                })
            }
        }
        try{
           exectutor(resolve,reject)
        }catch(err){
            //如果是 throw err直接手动调用reject
           reject(err)
        }
    }
    then(successFn,errFn){
        //判断 如果successFn不是一个函数 直接将结果返回 防止报错
        successFn= typeof successFn==='function' ? successFn:v=>v 
        errFn=typeof errFn==='function' ? errFn:err=>{throw err}
        //首先每次promise.then会返回一个新的promise
        let promise2=new Promise((resolve,reject)=>{
            if(this.status===RESOLVE){
                //拿到promise成功回调执行后的结果 判断是否是promise还是普通值.此时promise2还没有生成 需要异步执行 setTimeout
                 setTimeout(()=>{
                     //如果抛出异常 直接就reject返回错误结果
                     try{
                        let x=successFn(this.success_val)
                        resolvePromise(promise2,x,resolve,reject)
                     }catch(err){
                        reject(err)
                     }
                    
                 },0) //默认最少0.4毫秒执行
            }
            //反之
            if(this.status===REJECT){
                setTimeout(()=>{
                    //如果抛出异常 直接就reject返回错误结果
                    try{
                       let x=errFn(this.error_val)
                       resolvePromise(promise2,x,resolve,reject)
                    }catch(err){
                       reject(err)
                    }
                   
                },0) //默认最少0.4毫秒执行
            }
            //有异步操作这时promise的状态为pedding
            if(this.status===PENDING){
                this.success_arr.push(()=>{
                    //添加一个函数代码可拓展 增加别的逻辑 successFn执行的时候 当前状态已改为成功态 this.success的值已经改变
                    try{
                        let x=successFn(this.success_val)
                        resolvePromise(promise2,x,resolve,reject)
                     }catch(err){
                        reject(err)
                     }
                })
                this.err_arr.push(()=>{
                    try{
                        let x=errFn(this.error_val)
                        resolvePromise(promise2,x,resolve,reject)
                     }catch(err){
                        reject(err)
                     }
                })
            }
        }) 
       // 创建一个新的promise并返回
       return promise2;
    }
}

module.exports=Promise;

catch实现

catch(errFn){
  return this.then(null,errFn)
}

finally的实现

 //finally
finally(fn){
    this.then(value=>{
          fn()
          return value
     },err=>{
          fn()
          throw err
     })
 }

相关文章

  • promise的基本用法以及实现原理

    1.promise是什么? promise是异步编程的一种解决方案,解决多个异步方法串行的问题,比如回调地狱等.所...

  • Promise、async ,es6异步解决方案

    本文你将看到: promise介绍以及用法promise常用apidemo使用Promise实现一个简单axios...

  • Promise实现原理(附源码)

    本篇文章主要在于探究 Promise 的实现原理,带领大家一步一步实现一个 Promise , 不对其用法做说明,...

  • Promise扩展基础

    Promise.all基本用法: Promise.race基本用法: 直接调用成功状态: 函异步函数:

  • 实现 Promise

    实现 Promise 此代码基本源于大佬在掘金上发的文章Promise实现原理(附源码), 此文写得相当详细, 非...

  • Promise 对象

    Promise 的含义 基本用法 Promise.prototype.then() Promise.prototy...

  • promise详解

    Promise 用法api 1.基本用法 2.简便写法 Promise.all([]) Promise.race...

  • redux-promise解析

    redux-promise 解析这个中间的用法,以及原理 源码 用法 虽然官方文档上面并没有举例是如何使用(至这篇...

  • Promise 对象

    目录:Promise 的含义基本用法Promise.prototype.then()Promise.prototy...

  • Promise 的使用

    使用Promise 基本用法 A Promise is an object representing the ev...

网友评论

      本文标题:promise的基本用法以及实现原理

      本文链接:https://www.haomeiwen.com/subject/hsynuktx.html