美文网首页
手写Promise

手写Promise

作者: 疯狂吸猫 | 来源:发表于2020-03-20 15:32 被阅读0次

    参考:Promise实现原理(附源码)

    promise的注意点:

    Promise特点

    1.状态不可变

    2.值穿透,then的回调resolve要是不是一个function而是基本类型,那么这个基本类型就会传递给下一个then 关于promise的一道面试题

    3.then的回调resolvethrow erro会跳到下一个then回调的reject

    高阶函数:接收函数作为参数的函数

    高阶函数——廖雪峰

    1.一个最简单的高阶函数:

    function add(x, y, f) {//add为高阶函数
        return f(x) + f(y);
    }
    

    2.高阶函数决定了回调的调用时间以及接收的参数

    例如:高阶函数fn接收函数callBack作为参数,就决定了callBack的调用时间以及callBack的参数

    调用fn时定义callBack

    function fn(callBack) {//定义一个有回调的function——》fn
        //fn决定何时调用这个回调,以及对回调的传参
        callBack(1,2)
    }
    
    fn(function (fir,sec) {//调用fn传入回调,决定回调拿到传参的具体执行
        return fir+sec
    })
    

    3.高阶函数的回调接收的参数仍然是函数

    例如:

    定义高阶函数fn,并且给fn的回调传入函数

    调用fn时决定回调的具体内容,以及何时使用fn给的函数参数resolve、reject

    function fn(callBack) {//定义一个有回调的function——》fn
        //fn决定何时调用这个回调,以及对回调的传参
        let resolve=function(){
            console.log('resolve')
        }
        let reject=function(){
            console.log('reject')
        }
        
        callBack(resolve,reject)//对回调callBack的传参为函数
        
    }
    
    fn(function (resolve,reject) {//调用fn传入回调,决定回调拿到传参的具体执行
        return resolve()//回调的定义中决定什么时候使用收到的传参
    })
    
    

    Promise架构:

    1.new Promise().then()

    高阶函数的使用:

    new MyPromise(handle)的回调——>handles收到的参数为函数

    new MyPromise会执行calss MyPromise的构造函数,所以class MyPromise是在定义高阶函数,并且回调接收到的参数也就是函数(resolve、reject)。

    class MyPromise{//定义
        constructor(handle){
            handle(this.res,this.rej)
        }
        res(){}
    
        rej(){}
    }
    new MyPromise(function (resolve,reject) {//使用
        resolve(1)
    }).then()
    

    new MyPromise().then()表示执行MyPromise的构造函数之后立马执行then()

    then根据MyPromise实例使用的是resolve()还是reject()来选择回调

    所以resolve(),reject改变MyPromise中的this.state,then再根据this.state选择执行resolve还是reject

    此步骤完成代码如下:

    const PENDING = 'PENDING'//进行中
    const FULFILLED = 'FULFILLED'//已成功
    const REJECTED = 'REJECTED' //已失败
    
    class MyPromise{
        constructor(handle){
            this._value = null
            this._status = PENDING
            handle(this._resolve.bind(this),this._reject.bind(this))
        }
        _resolve(val){
            if (this._status !== PENDING) return//状态不可逆,只能从PENDING——》FULFILLED,不能从别的状态到FULFILLED
            this._value=val
            this._status=FULFILLED
        }
    
        _reject(val){
            if (this._status !== PENDING) return//状态不可逆,只能从PENDING——》REJECTED,不能从别的状态到REJECTED
            this._value= val
            this._status=REJECTED
        }
    }
    
    MyPromise.prototype.then=function (onFulfilled,onRejected) {
        switch (this._status) {
            case PENDING:break;
            case FULFILLED:onFulfilled(this._value);break;
            case REJECTED:onRejected(this._value);break;
        }
    
    }
    
    new MyPromise(function (resolve,reject) {
        resolve('call resolve')
    }).then(function (val) {
        console.log(val)
    })//call resolve
    
    new MyPromise(function (resolve,reject) {
        reject('call reject')
    }).then(function () {},function (val) {
        console.log(val)
    })//call reject
    
    

    注意:1. 高阶函数对this的处理:handle(this._resolve.bind(this),this._reject.bind(this)) 传递_resolve_rejecthandle调用,那么它们的this会随着hangle走,所以此处应该要bind

    2.Promise的状态不可变:由于只有_resolve_reject会修改状态,所以只要保证_resolve

    _reject修改状态前状态都为PENDING就可以做到状态不可变

    2.异步操作

    new MyPromise(handle1).then(handle1)是同步的,handle1执行之后会立刻执行then(),异步操作到任务队列中等待执行。但此时handle1的异步操作还没有执行,没有进行resolvereject所以then中的回调也无法执行。

    ​ 此时引入Pending(进行中)、Fulfilled(已成功)、Rejected(已失败)状态,resolve()可以将Pending转变为Fulfilled,同理reject()Pending转变为Rejected状态

    new MyPromise(handle1).then(handle1)执行到then()时如果有异步操作,那么状态仍为Peding,此时将then的回调都储存起来,等待resolve()、reject()执行时再执行。

    此步骤完成代码如下:

    const PENDING = 'PENDING'//进行中
    const FULFILLED = 'FULFILLED'//已成功
    const REJECTED = 'REJECTED' //已失败
    
    class MyPromise{
        constructor(handle){
            this._value = null
            this._status = PENDING
            // 添加成功回调函数队列
            this._fulfilledQueues = []
            // 添加失败回调函数队列
            this._rejectedQueues = []
            handle(this._resolve.bind(this),this._reject.bind(this))
        }
        _resolve(val){
            if (this._status !== PENDING) return//状态不可逆,只能从PENDING——》FULFILLED,不能从别的状态到FULFILLED
            this._value=val
            this._status=FULFILLED
            let cb
            while (cb=this._fulfilledQueues.shift()){//依次执行成功队列中的函数,并清空队列
                cb(val)
            }
        }
    
        _reject(val){
            if (this._status !== PENDING) return//状态不可逆,只能从PENDING——》REJECTED,不能从别的状态到REJECTED
            this._value= val
            this._status=REJECTED
            let cb
            while (cb=this._rejectedQueues.shift()){//依次执行失败队列中的函数,并清空队列
                cb(val)
            }
        }
    }
    
    //使用例子
    MyPromise.prototype.then=function (onFulfilled,onRejected) {
        switch (this._status) {
            case PENDING: this._fulfilledQueues.push(onFulfilled)//待选择,待执行的回头添加到队列
                          this._rejectedQueues.push(onRejected)
                          break
            case FULFILLED: onFulfilled(this._value);break;
            case REJECTED: onRejected(this._value);break;
        }
    
    }
    
    new MyPromise(function (resolve,reject) {
        setTimeout(function () {
            resolve('call resolve')
        },1000)
    
    }).then(function (val) {
        console.log(val)
    })//1秒之后输出 call resolve
    
    new MyPromise(function (resolve,reject) {
        setTimeout(function () {
            reject('call reject')
        },2000)
    
    }).then(function () {},function (val) {
        console.log(val)
    })//2秒之后输出 call reject
    
    

    3.链式调用

    3.1链式

    ​ 定义then方法时:

    ​ 让then返回一个MyPromise对象可实现链式调用。

    onFullfilled(val)onRejectedNext(val)的调用决定了new MyPromise().then().then(res,rej)中的第二个then的回调什么时候调用,收到的传参是多少。

    MyPromise.prototype.then(function(onFullfilled,onRejected){
        return new MyPromise(function(onFullfilledNext,onRejectedNext){
            onFullfilledNext(val)//onRejectedNext(val)
        })
    })
    

    3.2链式与异步

    常见情况下,onFullfilledNext的调用时间取决于onFullfilled的调用时间,onFullfilledNext(val)传递的参数valonFullfilled的返回值

    但是在异步情况下,onFullfilled是传入._fulfilledQueues队列中等待执行的,所以将onFullfilled打包在fulfilled中延迟调用,将fulfilled代替onFullfilled放入队列。fulfilledonFullfilledNext根据onFullfilled的返回值传参。

    此步骤代码:

    function isFunction(fn) {
        return typeof fn === 'function'
    }
    const PENDING = 'PENDING'//进行中
    const FULFILLED = 'FULFILLED'//已成功
    const REJECTED = 'REJECTED' //已失败
    
    class MyPromise{
        constructor(handle){
            this._value = null
            this._status = PENDING
            // 添加成功回调函数队列
            this._fulfilledQueues = []
            // 添加失败回调函数队列
            this._rejectedQueues = []
            try{
                handle(this._resolve.bind(this),this._reject.bind(this))
            }catch (err) {
                this._reject(err)
            }
    
        }
        _resolve(val){
    
            const run=() => {
                if (this._status !== PENDING) return//状态不可逆,只能从PENDING——》FULFILLED,不能从别的状态到FULFILLED
                // 依次执行成功队列中的函数,并清空队列
                const runFulfilled = (value) => {
                    let cb;
                    while (cb = this._fulfilledQueues.shift()) {
                        cb(value)
                    }
                }
    
                // 依次执行失败队列中的函数,并清空队列
                const runRejected = (error) => {
                    let cb;
                    while (cb = this._rejectedQueues.shift()) {
                        cb(error)
                    }
                }
    
                if(val instanceof MyPromise){
                    val.then((value)=>{
                        this._value=value
                        this._status=FULFILLED
                        runFulfilled(value)
                    },(err)=>{
                        this._value=err
                        this._status=REJECTED
                        runRejected(err)
                    })
                }else {
                    this._value=val
                    this._status=FULFILLED
                    runFulfilled(val)
                }
            }
            setTimeout(run,0)
    
        }
    
        _reject(err){
            if (this._status !== PENDING) return//状态不可逆,只能从PENDING——》REJECTED,不能从别的状态到REJECTED
    
            this._value= err
            this._status=REJECTED
            let cb
            while (cb=this._rejectedQueues.shift()){//依次执行失败队列中的函数,并清空队列
                cb(err)
            }
        }
    }
    
    MyPromise.prototype.then=function (onFulfilled,onRejected) {
        return new MyPromise( (onFulfilledNext,onRejectedNext) => {
            let fulfilled=(value) => {
                try {
                    let result = onFulfilled(value)
                        onFulfilledNext(result)
                }catch (err) {
                    onRejectedNext(err)
                }
            }
    
            let rejected=(value) => {
                try{
                    let result =onRejected(value)
                        onRejectedNext(result)
                }catch (err) {
                    onRejectedNext(err)
                }
            }
    
            switch(this._status){
                case PENDING : this._fulfilledQueues.push(fulfilled)
                    this._rejectedQueues.push(rejected)
                    break
                case FULFILLED :fulfilled(this._value)
                    break
                case REJECTED : rejected(this._value)
                    break
            }
        })
    
    }
    
    //使用例子
    new MyPromise(function (resolve,reject) {
        setTimeout(function () {
            resolve(new MyPromise(function (resolve) {
                resolve('promise in resolve')
            }))
        },1000)
    
    }).then(function (val) {
        console.log('first then,get message :'+val)//1秒之后输出 first then,get message :promise in resolve
        return 'val form 1st then to 2nd then'
    }).then(function (val) {
        console.log('second then,get message:'+val)//1秒之后输出 second then,get message:val form 1st then to 2nd then
    })
    
    

    3.3值穿透与then的回调返回MyPromise对象

    1.onFullfilled——》对应调用onFullfilledNext

    onFullfilled也就是第一个thenres回调

    onFullfilled不为function时:值穿透,直接onFullfilledNext(onFullFiled)

    onFullfilled为function时:1.如果返回值不为Promise,onFullfilledNext(返回值)

    ​ 2.如果返回值为Promise时,返回值.then(onFullfilled)。将onFullfilledNext传给then当回调,由Promise决定何时将执行权传递给then

    2.onRejected——》对应调用onRejectedNext

    onRejected也就是then的rej回调

    onRejected不为function时:值穿透,直接调用onRejectedNext(onRejected)

    onRejectedfunction时:1.返回值不为Promise,调用onRejectedNext(返回值)

    ​ 2.返回值为Promise,调用返回值.then(onRejectedNext)

    JS错误处理机制

    4.new Promise中resolve传递的值为Promise的实例

    resolve(new Promise)

    第一个Promise中状态取决于resolve中的Promise

    也就是说resolve中的Promise的then回调执行时就能确定第一个Promise的状态

    例如下面这种使用形式:

    new Promise(function (resolve,reject) {
       return resolve(new Promise(function () {
           
       }))
    }).then(function () {
    
    },function () {
    
    })
    

    所以在实现MyPromise中的_resolve时,如果_resolve(val)中的值为Promise的实例,instanceof val=== MyPromise 那么在val.then()的两个回调中改变MyPromise的状态

    代码

    function isFunction(fn) {
        return typeof fn === 'function'
    }
    const PENDING = 'PENDING'//进行中
    const FULFILLED = 'FULFILLED'//已成功
    const REJECTED = 'REJECTED' //已失败
    
    class MyPromise{
        constructor(handle){
            this._value = null
            this._status = PENDING
            // 添加成功回调函数队列
            this._fulfilledQueues = []
            // 添加失败回调函数队列
            this._rejectedQueues = []
            try{
                handle(this._resolve.bind(this),this._reject.bind(this))
            }catch (err) {
                this._reject(err)
            }
    
        }
        _resolve(val){
    
            const run=() => {
                if (this._status !== PENDING) return//状态不可逆,只能从PENDING——》FULFILLED,不能从别的状态到FULFILLED
                // 依次执行成功队列中的函数,并清空队列
                const runFulfilled = (value) => {
                    let cb;
                    while (cb = this._fulfilledQueues.shift()) {
                        cb(value)
                    }
                }
    
                // 依次执行失败队列中的函数,并清空队列
                const runRejected = (error) => {
                    let cb;
                    while (cb = this._rejectedQueues.shift()) {
                        cb(error)
                    }
                }
    
                if(val instanceof MyPromise){
                    val.then((value)=>{
                        this._value=value
                        this._status=FULFILLED
                        runFulfilled(value)
                    },(err)=>{
                        this._value=err
                        this._status=REJECTED
                        runRejected(err)
                    })
                }else {
                    this._value=val
                    this._status=FULFILLED
                    runFulfilled(val)
                }
            }
            setTimeout(run,0)
    
        }
    
        _reject(err){
            if (this._status !== PENDING) return//状态不可逆,只能从PENDING——》REJECTED,不能从别的状态到REJECTED
    
            this._value= err
            this._status=REJECTED
            let cb
            while (cb=this._rejectedQueues.shift()){//依次执行失败队列中的函数,并清空队列
                cb(err)
            }
        }
    }
    
    MyPromise.prototype.then=function (onFulfilled,onRejected) {
        return new MyPromise( (onFulfilledNext,onRejectedNext) => {
            let fulfilled=(value) => {
                if(!isFunction(onFulfilled)) {
                    onFulfilledNext(value) //值穿透
                    return
                }
    
                try {
                    let result = onFulfilled(value)
                    if(result instanceof MyPromise){
                        result.then(onFulfilledNext,onRejectedNext)
                    }else {
                        onFulfilledNext(result)
                    }
                }catch (err) {
                    onRejectedNext(err)
                }
            }
    
            let rejected=(value) => {
                if(!isFunction(onFulfilled)) {
                    onRejectedNext(value)
                    return
                }
                try{
                    let result =onRejected(value)
                    if(result instanceof  MyPromise){
                        result.then(onFulfilledNext,onRejectedNext)
                    } else {
                        onRejectedNext(result)
                    }
                }catch (err) {
                    onRejectedNext(err)
                }
            }
            switch(this._status){
                case PENDING : this._fulfilledQueues.push(fulfilled)
                               this._rejectedQueues.push(rejected)
                               break
                case FULFILLED :fulfilled(this._value)
                                break
                case REJECTED : rejected(this._value)
                                break
            }
        })
    }
    
    //使用例子
    new MyPromise(function (resolve,reject) {
        setTimeout(function () {
            resolve(new MyPromise(function (resolve) {
                resolve('promise in resolve')
            }))
        },1000)
    
    }).then(function (val) {
        console.log('first then,get message :'+val)//1秒之后输出 first then,get message :promise in resolve
        return new MyPromise(function (resolve) {
            setTimeout(()=>{
                return resolve('promise in then')
            },1000)
    
        })
    }).then(function (val) {
        console.log('second then ,get message:'+val)//2秒之后输出 second then ,get message:promise in then
    })
    
    

    相关文章

      网友评论

          本文标题:手写Promise

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