手撕Promise,从入门到入坟

第一章 准备

1.1.区别实例对象与函数对象

实例对象: new 函数产生的对象,称为实例对象,简称为对象

**函数对象: **将函数作为对象使用时,简称为函数对象

image-20221105214550670

1.2.二种类型的回调函数

1.2.1同步回调

1.理解: 立即执行, 完全执行完了才结束, 不会放入回调队列中
2.例子: 数组遍历相关的回调函数 / promise 的 excutor函数

1.2.2异步回调

image-20221105215936327

1.3.JS 的error处理

1.3.1错误的类型

  1. Error: 所有错误的父类型
  2. ReferenceError: 引用的变量不存在
  3. TypeError: 数据类型不正确的错误
  4. RangeError: 数据值不在其所允许的范围内
  5. SyntaxError: 语法错误

image-20221105222337791

第二章 promise的理解和使用

2.1为什么要用 Promise?

2.1.1.理解

1.抽象表达:

​ 1) Promise是一门新的技术(ES6规范)

​ 2) Promise是Js中进行异步编程的新解决方案

​ 备注:旧方案是单纯使用回调函数

  1. 具体表达:
    1. 从语法上来说: Promise是一个构造函数
    2. 从功能上来说: promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

2.1.2.promise的状态改变

  1. pending变为resolved

  2. pending 变为rejected

说明:只有这2种,且一个promise对象只能改变一次
无论变为成功还是失败,都会有一个结果数据
成功的结果数据一般称为value,失败的结果数据一般称为reason

2.1.3.promise的基本流程

img

2.1.4.promise的基本使用

image-20221105230329251

2.2为什么要用Promise?

2.2.1. 指定回调函数的方式更加灵活

  • 旧的: 必须在启动异步任务前指定
  • promise: 启动异步任务 → 返回promie对象 → 给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)

2.2.2.支持链式调用,可以解决回调地狱问题

1.什么是回调地狱?

  • 回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
  • image-20221105212836774

2.回调地狱的缺点?

  • 不便于阅读
  • 不便于异常处理

3.解决方案?

  • promise链式调用

4.终极解决方案?

  • async/await

image-20221106000713203

image-20221105235503392

<body>
    <script>

        // 原生的异步任务调用(回调会直接执行)
        function successCallback() { }
        function failureCallback() { }
        asyncAudioPlayer(options, successCallback, failureCallback);

        // Promise: 需要的时候再调用
        const promise = asyncAudioPlayer(options);
        setTimeout(() => {
            promise.then(successCallback, failureCallback);
        }, 3000)

        // 回调地狱: result1 -> doSomething1 -> result2 -> doSomething2 -> result3 -> doSomething3 
        doSomething1(function (result1) {
            doSomething2(result1, function (result2) {
                doSomething3(result2, function (result3) {
                    console.log(result3)
                }, failureCallback)
            }, failureCallback);
        }, failureCallback)

        // promise 使用promise的链式调用解决回调地狱
        doSomething1()                              // 第一层的函数
            .then(
                function (result1) {
                    return doSomething2(result1)    // 第二层的函数
                }
            ).then(
                function (result2) {
                    return doSomething3(result2)    // 第三层的函数
                }
            ).then(
                function (result3) {
                    return console.log(result3)
                }
            ).catch(failureCallback)


        // 使用 async/await
        async function asyncAudioPlayer() {
            try {
                let result1 = await doSomething1();
                let result2 = await doSomething2(result1);
                let result3 = await doSomething3(result2);
                console.log(result3)
            } catch (error) {
                failureCallback
            }
        }
    </script>
</body>

2.3如何使用Promise?

2.3.1.API

  1. Promise构造函数: Promise (executor){}

​ (1) executor函数: 执行器(resolve, reject)=> {}

​ (2)resolve函数: 内部定义成功时我们调用的函数value =>{}

​ (3) reject函数: 内部定义失败时我们调用的函数reason=>{}

​ 说明: executor会在Promise 内部立即同步回调, 异步操作在执行器中执行

  1. Promise.prototype.then方法: (onResolved, onRejected) =>{}
<body>
    <script>
        // 直接写在执行器内部
        new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("inner success data");
                // reject();    // 状态只能改变一次    
            }, 0)
        }).then(
            value => console.log(value)
        ).catch(
            reason => console.log(reason)
        )

        // Promise.resolve()
        Promise.resolve("outer success data").then(
            value => console.log(value)
        ).catch(
            reason => console.log(reason)
        )

        // 产生一个成功值为1 的promise
        const promise1 = new Promise((resolve, reject) => {
            resolve(1)
        })
        const promise2 = Promise.resolve(2)
        const promise3 = Promise.reject(3)

        promise1.then(value => console.log(value));
        promise2.then(value => console.log(value));
        promise3.catch(reason => console.log(reason));


        // Promise.all(value:list) : 所有成功后成功,只要一个失败就是失败
        const pall = Promise.all([promise1, promise2, promise3])
        pall.then(values => console.log(`onResolved return values:`, values));
        pall.catch(reason => console.log(`onrejected return reason: `, reason))     // this

        // Promise.race(value:list) :根据最先获取到的状态值,决定return (onrResolved \ onRejected)
        const prace = Promise.race([promise1, promise2, promise3])
        prace.then(value => console.log(`onResolved return value:`, value));        // this
        prace.catch(reason => console.log(`onRejected return reason:`, reason));

    </script>
</body>

2.3.2.promise 的几个关键问题

1.如何改变promise的状态?

​ (1) resolve(value):如果当前是pendding 就会变为resolved

​ (2) reject(reason):如果当前是pendding就会变为rejected

​ (3) 抛出异常:如果当前是pendding 就会变为rejected

<body>
    <script>
        const promise = new Promise((resolve, reject) => {

            // resolve(1);  // 确定promise的状态由: pending -> resolved
            // reject(2);   // 确定promise的状态由: pending -> rejected
            throw new Error('2 this is a rejected promise through throw new Error')

        })

        promise.then(value => console.log(value));
        promise.catch(reason => console.log(reason));
        console.log(promise);

        // promise status same call same status handler
        promise.then(value => console.log(value));
        promise.then(value => console.log(value));
        promise.catch(reason => console.log(reason));
        promise.catch(reason => console.log(reason));
    </script>
</body>

2.一个promise指定多个成功/失败回调函数,都会调用吗?
当promise改变为对应状态时都会调用

.then() # 为同步执行 .then(callback) # callback 为异步执行

3.改变promise状态和指定回调函数谁先谁后?

​ (1)都有可能,正常情况下是先指定回调再改变状态,但也可以先改状态再指定回调

​ (2)如何先改状态再指定回调?
​ ①在执行器中直接调用resolve()/reject()

​ ②延迟更长时间才调用then()

​ (3) 什么时候才能得到数据?

Promise:
	- then
	- 串联多任务
	- 异常穿透
	- 中断promise链

1.先指定promise的状态,后获取数据时,再给定回调函数。

// 1.此中写法是:先指定promise的状态,后获取数据时,再给定回调函数。
setTimeout(() => {
    (function () {
        const promise = new Promise((resolve, reject) => {
            // executor 范围是同步执行,而单独对:resolve\reject 函数来说,它是异步函数。
            console.log("(1) Promise inner env, 由于executor是属于同步回调,所以先执行, (2) resolve添加到了async queue, 此时的异步队列: [resolve,]")
            // resolve 表示的是成功的回调,中间的值表示返回的值,在执行器中直接书写,表示先指定promise的状态
            resolve(1);
        })
        // 对于.then 是同步函数,而.then(callback) 中的callback是异步函数。
        console.log("(3) Promise 同步回调 then, 发现callback 是异步回调,(4) 添加到 async queue中,此时的异步队列: [resolve,onResolved]")
        promise.then(
            value => { console.log("(6) Promise async return handler env"); console.log(value) }
        ) // 通过then()方法,延迟获取promise 返回的数据, 通过后面给定的回调函数对返回的数据进行处理。
        console.log('(5) Promise outer env')
    })();
});

2.先指定回调函数, 再指定Promise 状态的

// 2.此状态下的Promise 是先指定回调函数, 再指定Promise 状态的
setTimeout(() => {
    (function () {
        const promise = new Promise((resolve, reject) => {
            console.log("(1) executor 是同步回调, 执行到setTimeout 时发现,setTimeout是一个定时器,开启一个异步任务,同时将resolve(1)添加到异步队列中, 此时异步任务队列中的任务时:[resolve(1),]")
            setTimeout(() => { resolve(2); console.log("(5) setTimeout return Promise status pending => resolved") }, 200)
        })
        console.log("(2) .then 函数是同步回调, 执行到then(callback)中的callback时,发现callback是一个异步回调函数,将其添加到异步队列中:[resolve(1), value, reason]")
        promise.then(
            value => console.log('(4) Promise onResolved with value,发现promise 的状态一直是 pending 等待status的改变 (6)', value),
            reason => console.log("(4) Promise onRejected with reason, 发现promise 的状态一直是 pending 等待status的改变 (6)", reason)
        )
        console.log("(3) Promise outer env ")
    })();
}, 1000);

3. promise 多次被(单独)调用

// 3. 此为 promise 多次被(单独)调用
setTimeout(() => {
    (function () {
        // 第一次执行then 时获取的值,默认是resolve(值)的值, 后面的then,则需要通过返回或抛出获取值
        const promise = new Promise((resolve, reject) => {
            console.log("(1) executor area 同步回调执行, 发现resolve(3) 是异步函数,将其添加到异步队列中,[resolve(3)]")
            resolve(3)
        });
        console.log("(2) 执行promise.then()同步函数, 发现内容是异步函数,将异步函数添加到异步队列中,[resolve(3),value1, reason1]")
        promise.then(
            value => { console.log("(6) this Promise return onResolved value1: resolve(3) =>3", value); return 4 },
            reason => console.log("(6) Promise return onRejected reason1:", reason)
        );
        console.log("(3) 执行promise.then()同步函数, 发现内容是异步函数,将异步函数添加到异步队列中,[resolve(3),value1, reason1, value2, reason2]")
        promise.then(
            value => {
                console.log("(7) this Promise return onResolved value2: resolve(3) =>3", value);
                try {
                    throw new Error("5")
                } catch (error) {
                    console.log("(8) this Promise throw exception: 5", error.message);
                };
            },
            reason => console.log("(7) Promise return onRejected reason2:", reason)
        );
        console.log("(4) 执行promise.then()同步函数, 发现内容是异步函数,将异步函数添加到异步队列中,[resolve(3),value1, reason1, value2, reason2, value3, reason3]")
        promise.then(
            value => console.log("(9) this Promise return onResolved value3: resolve(3) =>3", value),
            reason => {
                console.log("(9) Promise return onRejected reason3:", reason);
                try {
                    throw new Error("6")
                } catch (error) {
                    console.log("(10) Promise throw exception:", error.message);
                };
            }
        )
        console.log("(5) Promise return:", promise)
    })();
}, 2000);

4. promise 多次被链式调用

// 4. 此为 promise 多次被链式调用(链式调用,Promise.then()的结果作为下一个then()的value,而then()执行是否成功则作为下一个then()的回调选择)
setTimeout(() => {
    (function () {
        // 第一次执行then 时获取的值,默认是resolve(值)的值, 后面的then,则需要通过返回或抛出获取值
        const promise = new Promise((resolve, reject) => {
            console.log("(1) executor area 同步回调执行,发现resolve(3) 是异步函数,将其添加到异步队列中,[resolve(3)]")
            resolve(4)
        }).then(
            value => { console.log("(4) this Promise return onResolved value1: resolve(4)=>4", value); return 5 },
            reason => console.log("(4) Promise return onRejected reason1: ", reason)
        ).then(
            value => {
                console.log("(5) this Promise return onResolved value2: return 5", value);
                throw new Error(6)
            },
            reason => console.log("(5) Promise return onRejected reason2:", reason)
        ).then(
            value => console.log("(7) Promise return onResolved value3:", value),
            reason => {
                console.log("(7) this Promise return onRejected reason3: Error message", reason);
                try {
                    throw new Error("7")
                } catch (error) {
                    console.log("(8) this Promise throw exception: 7", error.message);
                };
            }
        ).then(
            value => console.log("(9) this Promise return onResolved value4: undefined", value),
            reason => console.log("(8) Promise return onRejected reason4:", reason)
        )
        console.log("(2) 遇见 4 次 then 同步调用函数, 均发现器内容是 异步调用函数,先后将异步函数添加到异步队列中:[resolve(3),value1, reason1, value2, reason2, value3, reason3,value4,reason4]")
        console.log("(3) Promise return:", promise)
    })();
}, 2200);

5.同步与异步操作(return Promise setTimeout)

setTimeout(() => {
    (function () {
        const promise = new Promise((resolve, reject) => {
            console.log("(1) executor area env resolve 1, 添加到异步队列中: [resolve(1),]")
            resolve(1)
        }).then(
            value1 => {
                console.log("(2) resolve(1) onResolved return value1 1", value1)
                setTimeout(() => {
                    console.log("(5) setTimeout value1 onResolved return ,添加到异步队列中[resolve(1),value1,value2,reason2,value1_setTimeout, return_setTimeout]")
                })
                return new Promise((resolve, reject) => {
                    console.log("(3) Promise executor area env resolve")
                    setTimeout(() => {
                        console.log("(6) return promise onResolved setTimeout")
                        reject(2)
                        // resolve(2)
                    })
                })
            }
        ).then(
            value2 => console.log("(4)(7) setTimetout onResolved reject(2)  reason2 2", value2),
            reason2 => console.log("(4)(7) this setTimetout onRjected reject(2)  reason2 2", reason2)
        )
        })();
}, 2400)

6.同步与异步操作(return setTimeout Promise)

setTimeout(() => {
    (function () {
        const promise = new Promise((resolve, reject) => {
            console.log("(1) executor area env resolve 1, 添加到异步队列中: [resolve(1),]")
            resolve(1)
        }).then(
            value1 => {
                console.log("(2) resolve(1) onResolved return value1 1", value1)
                setTimeout(() => {
                    console.log("(4) setTimeout value1 onResolved return ,添加到异步队列中")
                })
                return setTimeout(() => {
                    console.log("(5) value1 setTimeout")
                    return new Promise((resolve, reject) => {
                        console.log("(6) resolve ")
                        let r = resolve(2)
                        console.log("(7) resolve(2) return", r) // undefined
                    })
                })   // return value is setTimeout ID
            }
        ).then(
            value2 => {
                console.log("(3) setTimetout onResolved resolve(2)  reason2 2",)
                setTimeout(() => { console.log("(8) this get setTimeout id", value2) }, 300)
            },
            reason2 => console.log("(3) setTimetout onRjected reject(2)  reason2 2", reason2)
        )
        })();
}, 3000)

7.异常穿透

// 异常穿透
const promise = new Promise((resolve, reject) => {
    reject(1)
}).then(
    value => console.log(value),
).then(
    value => console.log(value),
    reason => { return Promise.reject(reason) },
).then(
    value => console.log(value),
    reason => { throw reason }
).catch(
    reason => console.log(reason)
)

8.中断promise链

// 中断Promise链
const promise1 = new Promise((resolve, reject) => {
    reject(1)
}).then(
    value => console.log(value),
).then(
    value => console.log(value),
    reason => { return new Promise(() => { }) },    // Promise status pending
).catch(
    reason => console.log(reason)
)

第三章 自定义(手写) Promise

函数式(宏定义)

/*
暴露: es5 iife
方法:
    Promise.all()
    Promise.allSettled()
    Promise.any()
    Promise.race()
    Promise.reject()
    Promise.resolve()

    Promise.prototype.then()
    Promise.prototype.catch()
    Promise.prototype.finally()
*/
(function (window) {
    /*
        1.Promise 构造函数
        传入执行函数,
        返回一个新的Promise对象
    */

    const PENDING = "pending"
    const RESOLVED = "resolved"
    const REJECTED = "rejected"

    const ONRESOLVED = "onResolved"
    const ONREJECTED = "onRejected"

    function Promise(executor) {
        this.data = undefined
        this.status = "pending"
        this.callback = []

        let that = this

        function resolve(value) {
            // 只有当 status 为 pending 时才继续执行
            if (that.status !== PENDING) return
            that.data = value
            that.status = RESOLVED
            // add_async_callback(value, ONRESOLVED)
            if (that.callback.length > 0) {
                setTimeout(() => {
                    that.callback.forEach((callbacksObj) => {
                        callbacksObj.onResolved(value)
                    })
                })
            }
        }
        function reject(reason) {
            // 只有当 status 为 pending 时才继续执行
            if (that.status !== PENDING) return
            that.data = reason
            that.status = REJECTED
            // add_async_callback(reason, ONREJECTED)
            if (that.callback.length > 0) {
                setTimeout(() => {
                    that.callback.forEach((callbacksObj) => {
                        callbacksObj.onRjected(reason)
                    })
                })
            }
        }

        // 执行器函数调用,捕获异常
        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }

    }

    /*
    2.Promise 原型上的方法 proptotype  (then,catch, finally)
        then:
            - 传入onResolved,onRjected
            - 返回一个新的Promise
        catch:
            - 传入onRjected
            - 返回一个
    */
    Promise.prototype.then = function (onResolved, onRjected) {
        /*
        1.如果抛出异常, return的promise就会失败,reason就是error
        2.如果回调函数返回不是promise,return的promise就会成功,value就是返回的值
        3.如果回调函数返回是promise,return的promise结果就是这个promise的结果
        */

        let that = this
        //指定默认的失败的回调(实现错误/异常传透的关键点)
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
        onRjected = typeof onRjected === 'function' ? onRjected : reason => { throw reason }

        return new Promise((resolve, reject) => {
            function handle(callback) {
                try {
                    const result = callback(that.data)
                    if (result instanceof Promise) {
                        result.then(resolve, reject)
                    } else {
                        resolve(result)
                    }
                } catch (error) {
                    reject(error)
                }
            }
            setTimeout(() => {
                if (that.status === REJECTED) {
                    handle(onRjected)
                } else if (that.status === RESOLVED) {
                    handle(onResolved)
                } else {
                    that.callback.push({
                        onResolved(value) {
                            handle(onResolved)
                        },
                        onRjected(reason) {
                            handle(onRjected)
                        },
                    })
                }
            })
        })
    }

    Promise.prototype.catch = function (onRjected) {
        return this.then(undefined, onRjected)
    }
    Promise.prototype.finally = function () { }

    Promise.resolve = function (value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) { value.then(resolve, reject) } else {
                resolve(value)
            }
        })
    }
    Promise.reject = function (value) {
        return new Promise((_, reject) => {
            reject(value)
        })
    }

    // 自定义 延时
    Promise.resolveDelay = function (value, timeout) {
        setTimeout(() => {
            Promise.resolve(value);
        }, timeout);
    }
    Promise.rejectDelay = function (reason, timeout) {
        setTimeout(() => {
            Promise.reject(reason);
        }, timeout);
    }


    //返回一个promise,只有当所有proimse都成功时才成功,否则只要有一个失败的就失败
    Promise.all = function (promises) {
        // promises 是一个Promise队列, all 的功能就是,将队列中所有的Promise的状态 一假为假(返回状态为rejected的 reason)
        const resolvedArray = new Array(promises.length);
        let resolvedCount = 0;
        return new Promise((resolve, reject) => {
            promises.forEach((p, index) => {      
                Promise.resolve(p).then(
                    values => {
                        resolvedCount++
                        resolvedArray[index] = values
                        // 如果全部成功,则返回一个成功的Promise [value1, value2, ...]
                        if (resolvedCount === promises.length) {
                            resolve(resolvedArray)
                        }
                    },
                    reason => {
                        // 如果一个出错,直接返回第一个出错的Promise的reason
                        reject(reason)
                    });
            })
        })
    }

    
    //返回一个promise,其结果由第一个完成的promise决定
    Promise.race = function (promises) {
        return new Promise((resolve, reject) => {
            promises.forEach(p => {
                Promise.resolve(p).then(
                    value => {
                        resolve(value);
                    },
                    reason => {
                        reject(reason);
                    }
                )
            })
        })
    }


    window.Promise = Promise;
})(window);

类方法(宏定义)

(function (window) {

    const PENDING = "pending"
    const RESOLVED = "resolved"
    const REJECTED = "rejected"
    ISFUCTION = fn => typeof fn === "function"

    class MyPromise {

        constructor(executor) {
            this._status = PENDING
            this._value = undefined
            this._reason = undefined
            this._fulfilledQueue = [];
            this._rejectedQueue = [];

            if (!ISFUCTION(executor)) {
                throw new Error("Promise must accept a function as a parameter")
            }

            try {
                executor(this._resolve.bind(this), this._reject.bind(this))
            } catch (error) {
                this._reject(error)
            }
        }

        static resolve(value) {
            return new MyPromise((resolve, reject) => {
                if (value instanceof MyPromise) {
                    value.then(resolve, reject)
                } else {
                    resolve(value)
                }
            })
        }

        static reject(reason) {
            return new MyPromise((_, reject) => {
                reject(reason)
            })
        }

        static all(MyPromises) {
            let resolveCount = 0
            let resolvedAll = new Array(MyPromises.length)
            return new MyPromise((resolve, reject) => {
                MyPromises.forEach((p, index) => {
                    MyPromise.resolve(p).then(
                        value => {
                            resolveCount++
                            resolvedAll[index] = value
                            if (resolveCount === MyPromises.length) {
                                resolve(resolvedAll)
                            }
                        },
                        reason => {
                            reject(reason)
                        }
                    )
                })
            })
        }

        static race(MyPromises) {
            return new MyPromise((resolve, reject) => {
                MyPromises.forEach((p) => {
                    MyPromise.resolve(p).then(
                        value => {
                            resolve(value)
                        },
                        reason => {
                            reject(reason)
                        }
                    )
                })
            })
        }


        _resolve(value) {
            if (this._status !== PENDING) return
            this._status = RESOLVED
            this._value = value
            setTimeout(() => {
                if (this._fulfilledQueue.length > 0) {
                    this._fulfilledQueue.forEach(callback => { callback.onResolved(value) })
                }
            })
        }

        _reject(reason) {
            if (this._status !== PENDING) return
            this._status = REJECTED
            this._reason = reason
            setTimeout(() => {
                if (this._rejectedQueue.length > 0) {
                    this._rejectedQueue.forEach(callback => { callback.onRejected(reason) })
                }
            })
        }

        then(onResolved, onRejected) {
            onResolved = typeof onResolved === 'function' ? onResolved : value => value
            onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
            return new MyPromise((resolve, reject) => {
                const handle = (callback, resolve, reject) => {
                    try {
                        const result = callback(this._value || this._reason)
                        if (result instanceof MyPromise) {
                            result.then(resolve, reject)
                        } else {
                            resolve(result)
                        }
                    } catch (error) {
                        reject(error)
                    }
                }
                setTimeout(() => {
                    if (this._status === REJECTED) {
                        handle(onRejected, resolve, reject)
                    } else if (this._status === RESOLVED) {
                        handle(onResolved, resolve, reject)
                    } else {
                        const ResolvedFn = { onResolved(value) { handle(onResolved, resolve, reject) } }
                        const RejectedFn = { onRejected(reason) { handle(onRejected, resolve, reject) } }
                        this._fulfilledQueue.push(ResolvedFn)
                        this._rejectedQueue.push(RejectedFn)
                    }
                })
            })
        }

        catch(onRjected) {
            return this.then(undefined, onRjected)
        }
    }

    window.MyPromise = MyPromise;
})(window);

第四章 宏队列与微队列

image-20221109120305299

1.JS 中用来存储待执行回调函数的队列包含2个不同特定的列队

2.宏列队: 用来保存待执行的宏任务(回调),比如: 定时器回调/ DOM事件回调/ ajax回调
3.微列队: 用来保存待执行的微任务(回调),比如: promise的回调 / MutationObserver的回调
4.JS执行时会区别这两个队列
(1)JS引擎首先必须先执行所有的初始化同步任务代码
(2)每次准备取出第一个宏任务执行前,都要将所有的微任务一个一个取出来执行

优先执行顺序: 同步代码 > 微队列[微任务, ...] > 宏队列 [宏任务, ...]

/*
    1.顺序宏任务添加到宏队列
    2.同步任务 先执行
    3.状态确定立即调用then, 将异步存储callback, 若前then未执行,将其缓存,等前then执行后再添加
    4.状态未定,先等待
    调用then(表示已经确定状态)
*/

第五章 面试题

一、面试题

面试题1

setTimeout(() => {
    console.log(1)
}, 0)
Promise.resolve().then(() => {
    console.log(2)
})
Promise.resolve().then(() => {
    console.log(4)
})
console.log(3)

面试题2

setTimeout(() => {
    console.log(1)
}, 0)
new Promise((resolve) => {
    console.log(2)
    resolve()
}).then(() => {
    console.log(3)
}).then(() => {
    console.log(4)
})
console.log(5)

面试题3

const first = () => (new Promise((resolve, reject) => {
    console.log(3)
    let p = new Promise((resolve, reject) => {
        console.log(7)
        setTimeout(() => {
            console.log(5)
            resolve(6)
        }, 0)
        resolve(1)
    })
    resolve(2)
    p.then((arg) => {
        console.log(arg)
    })
}))
first().then((arg) => {
    console.log(arg)
})
console.log(4)

面试题4

setTimeout(() => {
    console.log("9")
}, 0)
new Promise((resolve, reject) => {
    console.log("1")
    resolve()
}).then(() => {
    console.log("2")
    new Promise((resolve, reject) => {
        console.log("3")
        resolve()
    }).then(() => {
        console.log("4")
    }).then(() => {
        console.log("5")
    })
}).then(() => {
    console.log("6")
})

new Promise((resolve, reject) => {
    console.log("7")
    resolve()
}).then(() => {
    console.log("8")
})

面试题5

手写 promise

二、答案

面试题1:3 2 4 1

面试题2:2 5 3 4 1

面试题3:3 7 4 1 2 5

面试题4:1 7 2 3 8 4 6 5 9

手写promise见第三章

posted @ 2022-11-21 17:48  Redskaber  阅读(92)  评论(0)    收藏  举报