摘要:简单的promise链式调用代码解释

promise的很简单的一个实现


// 三种状态
const PENDING = Symbol()
const FULFILLED = Symbol()
const REJECTED = Symbol()

function Promisee(fn) {
    // fn 必须是函数
    if (typeof fn !== 'function') {
        throw new Error('fn must be a function!')
    }

    let state = PENDING // 初始状态是 PENDING
    let value = null // 返回值
    let handler = {}

    function fulfill (result) {
        state = FULFILLED
        value = result
        next(handler)
    }

    // 完成时调用的方法,这里做了容错
    function resolve (result) {
        try {
            fulfill(result)
        } catch (err) {
            reject(err)
        }
    }

    // 拒绝时调用的方法
    function reject (error) {
        state = REJECTED
        value = error
        next(handler)
    }

    function next({ onFulfill, onReject }) {
        switch (state) {
            case FULFILLED:
                onFulfill && onFulfill(value)
                break
            case REJECTED:
                onReject && onReject(value)
                break
            case PENDING:
                handler = { onFulfill, onReject }
        }
    }

    this.then = function (onFulfill, onReject) {
        return new Promisee((resolve, reject) => {
            next({
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
            })
        })
    }

    fn(resolve, reject)
}

let p  =new Promisee((resolve,reject) => {reject('hello');})
//let p  =new Promisee((resolve,reject) => {setTimeout(() => reject('hello'),0)});
p.then(console.log.bind(null,'over'),console.error.bind(null,'error')).then(console.log.bind(null,'over'),console.error.bind(null,'error'))

执行顺序

异步调用

fn1 -> then -> resolve/reject -> then 回调

同步调用

fn1 -> resolve/reject -> then -> then 回调

异步调用详细解释

let p  =new Promisee((resolve,reject) => {setTimeout(() => resolve('hello'),0)});
p.then(console.log.bind(null,'over'),console.error.bind(null,'error')).then(console.log.bind(null,'over'),console.error.bind(null,'error'));

//为了方便解释 上面的代码可以看成

let p1  =new Promisee((resolve,reject) => {setTimeout(() => resolve('hello'),0)});
let p2 = p1.then(console.log.bind(null,'over'),console.error.bind(null,'error'));
let p3 = p2.then(console.log.bind(null,'over'),console.error.bind(null,'error'));

1.先new Promisee一个对象p1
2.p1将传入的(resolve,reject) => {setTimeout(() => reject('hello'),0)}当作fn(resolve, reject)
3.执行setTimeout将() => reject('hello')放入宏任务队列
4.执行p1.then(console.log.bind(null,'over'),console.error.bind(null,'error'))
5.p1.then返回一个对象p2
6.p1.then返回的对象p2开始将

(resolve, reject) => {
            next({
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
            })
        }

当作fn(resolve, reject)执行
7.注意

(resolve, reject) => {
next({
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
            })
       }

的执行环境是p1,也就是next会在p1这个对象下执行。而其中的resovle则会在p2对象执行。

详情见:https://www.keepnight.com/archives/145/

8.因为p1的state为PENDING,所以会把next函数里面的

{
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
}

这个对象放入p1对象的handle里。画重点:resolve和reject是p2对象中的
9.得到p2对象后,p2调用p2.then(console.log.bind(null,'over'),console.error.bind(null,'error'))返回一个对象p3
10.p2.then返回的对象p3开始将

(resolve, reject) => {
            next({
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
            })
        }

当作fn(resolve, reject)执行
11.因为p2的state为PENDING,所以会把next函数里面的

{
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
}

这个对象放入p2对象的handle里。画重点:resolve和reject是p3对象中的
12.主线程执行完毕,开始执行setTimeout宏任务。() => resolve('hello')函数执行改变p1中的state为FULFILLED,接着调用p1的resolve方法next(handler),而handler里面放的是

{
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
}

就相当于先执行onFulfill(val)(或者说p1.then中的第一个回调函数),然后调用来自p2的resolve方法,改变p2的state为FULFILLED。接着调用来自p2的resolve方法中的next(handler),而handler里面放的是

{
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
}

就相当于先执行onFulfill(val)(或者说p2.then中的第一个回调函数),然后调用来自p3的resolve方法,改变p3的state为FULFILLED.

同步调用详细解释

let p  =new Promisee((resolve,reject) => {resolve('hello');})
p.then(console.log.bind(null,'over'),console.error.bind(null,'error')).then(console.log.bind(null,'over'),console.error.bind(null,'error'));

//为了方便解释 上面的代码可以看成

let p1  =new Promisee((resolve,reject) => {resolve('hello');});
let p2 = p1.then(console.log.bind(null,'over'),console.error.bind(null,'error'));
let p3 = p2.then(console.log.bind(null,'over'),console.error.bind(null,'error'));

1.先new Promisee一个对象p1
2.p1将传入的(resolve,reject) => {reject('hello');}当作fn(resolve, reject)
3.fn(resolve, reject)直接执行将p1中的state设定为FULFILLED,并将value赋值为'hello'
4.p1.then返回一个对象p2
5.p1.then返回的对象p2开始将

(resolve, reject) => {
            next({
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
            })
        }

当作fn(resolve, reject)执行,next会在p1这个对象下执行,其中的resovle则会在p2对象执行。
6.因为p1中的state为FULFILLED,value赋值为'hello',所以调用

 onFulfill: val => {
                    resolve(onFulfill(val))
                },

先执行p1.then中的第一个回调函数,然后将这个函数的返回值传递给p2对象,resolve将p2对象的state设置为FULFILLED,p2对象的vaule设置为onFulfill(val)的返回值
7.p2对象调用p2.then返回一个对象p3
8.p2.then返回的对象p3开始将

(resolve, reject) => {
            next({
                onFulfill: val => {
                    resolve(onFulfill(val))
                },
                onReject: err => {
                    reject(onReject(err))
                }
            })
        }

当作fn(resolve, reject)执行,next会在p2这个对象下执行,其中的resovle则会在p3对象执行。
6.因为p2中的state为FULFILLED,value赋值为undefined,所以调用

 onFulfill: val => {
                    resolve(onFulfill(val))
                },

先执行p2.then中的第一个回调函数,然后将这个函数的返回值传递给p3对象,resolve将p3对象的state设置为FULFILLED,p3对象的vaule设置为onFulfill(val)的返回值。

链接:
promise官方实现代码

文章目录