Promise

1、Promise是一个类,类中须要传入一个executor执行器,默认会立刻执行
2、Promise有三种状态, pending , resolved , rejected , 只能从期待态转为其余两种状态
3、promise官网标准:https://promisesaplus.com/
4、promise反对链式调用,外部原理采纳的是公布订阅模式
5、每次调用then办法,都会返回一个新的promise
6、.then中什么时候走失败:返回的是一个失败的promise,抛出异样也会走失败,其余都走胜利
7、catch用来对立捕捉谬误,它的特点是:如果一层层往下找,都没有处理错误的函数,则会找到最近的catch,catch也是then, 遵循then的规定

第一版:没有任何异步逻辑

const PENDING = 'PENDING'const RESOLVED = 'RESOLVED'const REJECTED = 'REJECTED'class Promise {    constructor(executor) {        this.status = PENDING;        this.value = undefined        this.reason = undefined        let resolve = (value) => {            if (this.status === PENDING) {                this.value = value                this.status = RESOLVED            }        }        let reject = (reason) => {            if (this.status === PENDING) {                this.reason = reason                this.status = REJECTED            }        }        try {//为什么加try..catch,因为外部可能间接出错            executor(resolve, reject)//给用户提供两个函数        } catch (e) {            reject(e)        }    }    then(onfulfilled, onrejected) {        if (this.status === RESOLVED) {            onfulfilled(this.value)        }        if (this.status === REJECTED) {            onrejected(this.reason)        }    }}module.exports = Promise

第二版:如果executor外面有异步操作,则须要采纳公布订阅模式进行解决

const PENDING = 'PENDING'const RESOLVED = 'RESOLVED'const REJECTED = 'REJECTED'class Promise {    constructor(executor) {        this.status = PENDING;        this.value = undefined        this.reason = undefined        // 专门寄存胜利的回调的函数        this.onResolvedCallbacks = [];        // 专门寄存失败的回调函数的        this.onRejectedCallbacks = [];        let resolve = (value) => {            if (this.status === PENDING) {                this.value = value                this.status = RESOLVED                // 当调用resolve时,阐明要走胜利态,所以顺次执行then中胜利的回调                this.onResolvedCallbacks.forEach(fn => fn())            }        }        let reject = (reason) => {            if (this.status === PENDING) {                this.reason = reason                this.status = REJECTED                // 当调用reject时,阐明要走失败态,所以执行then中失败的回调                this.onRejectedCallbacks.forEach(fn => fn())            }        }        try {            executor(resolve, reject)        } catch (e) {            reject(e)        }    }    then(onfulfilled, onrejected) {        if (this.status === RESOLVED) {            onfulfilled(this.value)        }        if (this.status === REJECTED) {            onrejected(this.reason)        }        //如果有异步操作(如setTimeout),执行then办法时状态还是PENDING,则须要将then中的两个办法先存起来        if (this.status === PENDING) {            //第一种:将这个函数间接扔进去,然而不太好,不不便扩大本人的性能            // this.onResolvedCallbacks.push(onfulfilled)            // this.onRejectedCallbacks.push(onrejected)            // 第二种:应用切片编程,外面包一层,不便扩大            this.onResolvedCallbacks.push(() => {                onfulfilled(this.value)            })            this.onRejectedCallbacks.push(() => {                onrejected(this.reason)            })        }    }}module.exports = Promise

第三版:then的链式调用及then是个异步操作

const PENDING = 'PENDING'const RESOLVED = 'RESOLVED'const REJECTED = 'REJECTED'// 个别微工作比宏工作早执行,也不是相对的,setTimeout是宏工作// 判断x的状态 是让promise2走胜利态还是失败态function resolvePromise(promise2, x, resolve, reject) {    // TODO}class Promise {    constructor(executor) {        this.status = PENDING;        this.value = undefined        this.reason = undefined        this.onResolvedCallbacks = [];        this.onRejectedCallbacks = [];        let resolve = (value) => {            if (this.status === PENDING) {                this.value = value                this.status = RESOLVED                this.onResolvedCallbacks.forEach(fn => fn())            }        }        let reject = (reason) => {            if (this.status === PENDING) {                this.reason = reason                this.status = REJECTED                this.onRejectedCallbacks.forEach(fn => fn())            }        }        try {            executor(resolve, reject)        } catch (e) {            reject(e)        }    }    then(onfulfilled, onrejected) {        // 链式调用,返回的须要是个新的promise        const promise2 = new Promise((resolve, reject) => {            // 将之前判断条件放到这个promise的外面,因为它是promise,所以是立刻执行,不影响            if (this.status === RESOLVED) {                //将then执行之后的后果传到下一个promise的resolve或者reject中                // 须要判断这个x是一般值还是promise,如果是promise,则须要让这个promise执行,执行之后的状态将作为promise2的状态                setTimeout(() => {//为什么须要setTimeout?因为官网说了then是个异步操作                    try {//为什么要包住,因为执行onfulfilled可能会出错                        let x = onfulfilled(this.value)                        // 我须要依据x,判断调用promise2的resolve还是reject,所以将promise2和它的resolve和reject传过来                        // 此时应该没有promise2,应该怎么搞?答案就是通过增加宏工作(setTimeout)或者微工作(nextTick)                        resolvePromise(promise2, x, resolve, reject)                    } catch (e) {                        reject(e)                    }                }, 0)            }            if (this.status === REJECTED) {                setTimeout(() => {                    try {                        let x = onrejected(this.reason)                        resolvePromise(x)                    } catch (e) {                        reject(e)                    }                }, 0);            }            if (this.status === PENDING) {                this.onResolvedCallbacks.push(() => {                    setTimeout(() => {                        try {                            let x = onfulfilled(this.value)                            resolvePromise(x)                        } catch (e) {                            reject(e)                        }                    }, 0);                })                this.onRejectedCallbacks.push(() => {                    setTimeout(() => {                        try {                            let x = onrejected(this.reason)                            resolvePromise(x)                        } catch (e) {                            reject(e)                        }                    }, 0);                })            }        })    }}module.exports = Promise

第四版:resolvePromise办法的实现

const PENDING = 'PENDING'const RESOLVED = 'RESOLVED'const REJECTED = 'REJECTED'function resolvePromise(promise2, x, resolve, reject) {    // 此办法 为了兼容所有的promise,n个库两头 执行的流程是一样的    // 尽可能具体 不出错    // 1) 不能引用同一个对象 可能会造成死循环    if (promise2 === x) {        return reject(new TypeError('Chaining cycle detected for promise #<Promise> --'))    }    let called;    // 2) 判断x的类型 x是对象或者函数,才有可能是promise    if ((typeof x === 'object' && x != null) || typeof x === 'function') {        try {            let then = x.then;  // {a:1} 因为then办法 可能应用的getter来定义的            if (typeof then === 'function') { // 只能认为他是promise了                // call 扭转this指向 并且让函数执行                then.call(x, y => { // 只取一次 以后promise解析进去的后果可能还是一个promise持续解析直到他是一个一般值为止                    if (called) return;                    called = true;                    // 递归解析resolve的值                    resolvePromise(promise2, y, resolve, reject)                }, r => {                    if (called) return;                    called = true;                    reject(r);                })            } else {                // 如果不是函数,则只能是这种对象了{a:1,then:1}                resolve(x)            }        } catch (e) { //  我取then出错了 在谬误中又掉了该promise的胜利            if (called) return            called = true;            reject(e); //取值失败 就走到error中        }    } else {        // 进到这里阐明是一般值,走胜利态        resolve(x)    }}class Promise {    constructor(executor) {        this.status = PENDING;        this.value = undefined        this.reason = undefined        this.onResolvedCallbacks = [];        this.onRejectedCallbacks = [];        let resolve = (value) => {            if (this.status === PENDING) {                this.value = value                this.status = RESOLVED                this.onResolvedCallbacks.forEach(fn => fn())            }        }        let reject = (reason) => {            if (this.status === PENDING) {                this.reason = reason                this.status = REJECTED                this.onRejectedCallbacks.forEach(fn => fn())            }        }        try {            executor(resolve, reject)        } catch (e) {            reject(e)        }    }    catch(errCallback){ // catch就是没有胜利的then办法        return this.then(null,errCallback)    }    then(onfulfilled, onrejected) {        const promise2 = new Promise((resolve, reject) => {            if (this.status === RESOLVED) {                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(x)                    } catch (e) {                        reject(e)                    }                }, 0);            }            if (this.status === PENDING) {                this.onResolvedCallbacks.push(() => {                    setTimeout(() => {                        try {                            let x = onfulfilled(this.value)                            resolvePromise(x)                        } catch (e) {                            reject(e)                        }                    }, 0);                })                this.onRejectedCallbacks.push(() => {                    setTimeout(() => {                        try {                            let x = onrejected(this.reason)                            resolvePromise(x)                        } catch (e) {                            reject(e)                        }                    }, 0);                })            }        })    }}module.exports = Promise// npm install -g promises-aplus-tests

常见面试题

  • promise链式调用原理和jquery链式调用原理区别
答:jquery中的链式调用原理是通过返回this实现的,而promise的链式调用是通过返回新的promise实现的
  • Promise.all办法的原理
答:all办法的特点是让所有的promise并发执行,外部应用**计数器**的形式判断是否全副执行完了,外部应用递归
  • Promise.resolve 和 Promise.reject区别
答:Promise.resolve()参数能够承受一个promise,并且期待它状态扭转;Promise.reject()也能够承受promise,然而不会有期待成果,间接会走失败态