鏍规嵁 Promise/A+ 鍜?ES6 瑙勮寖锛屽疄鐜?Promise 婧愮爜锛堥檮璇︾粏娉ㄩ噴鍜屾祴璇曪級

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鏍规嵁 Promise/A+ 鍜?ES6 瑙勮寖锛屽疄鐜?Promise 婧愮爜锛堥檮璇︾粏娉ㄩ噴鍜屾祴璇曪級相关的知识,希望对你有一定的参考价值。

鏍囩锛?a href='http://www.mamicode.com/so/1/script' title='script'>script   rip   绀轰緥   status   sap   generator   浠诲姟闃熷垪   previous   gen   

Promise

婧愮爜 https://github.com/lfp1024/promise

promise-a-plus

const PENDING = 鈥楶ENDING鈥?const REJECTED = 鈥楻EJECTED鈥?const RESOLVED = 鈥楻ESOLVED鈥?
const resolvePromise = (promise2, x, resolve, reject) => {
    if (promise2 === x) {
        // ES6 瑙勮寖鍐欐硶 鏃犳硶閫氳繃Promise/A+娴嬭瘯
        // return reject(鈥榌TypeError: Chaining cycle detected for promise #<Promise>]鈥?
        // Promise/A+ 瑙勮寖鍐欐硶
        return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
    }

    let called

    if ((typeof x === 鈥榦bject鈥?&& x !== null) || typeof x === 鈥榝unction鈥? {
        try {
            const then = x.then
            if (typeof then === 鈥榝unction鈥? {
                then.call(x, y => {
                    if (called) return
                    called = true
                    resolvePromise(promise2, y, resolve, reject)
                }, e => {
                    if (called) return
                    called = true
                    reject(e)
                })
            } else {
                resolve(x)
            }
        } catch (error) {
            if (called) return
            called = true
            reject(error)
        }
    } else {
        resolve(x)
    }
}

class Promise {

    constructor(executor) {
        if (typeof executor !== 鈥榝unction鈥? {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }

        this.status = PENDING
        this.value = undefined

        this.onResolvedCallbackArr = []
        this.onRejectedCallbackArr = []

        const resolve = (value) => {
            // resolve涓娇鐢ㄦā鏉垮瓧绗︿覆锛屾棤娉曢€氳繃Promise/A+娴嬭瘯
            // console.log(`${value}`)
            if (value === this) {
                return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
            }

            if (value instanceof Promise) {
                return value.then(resolve, reject)
            }

            // resolve瑙f瀽thenable瀵硅薄鏄疎S6鐨勫姛鑳斤紝鏃犳硶閫氳繃Promise/A+娴嬭瘯
            // if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
            //     typeof value.then === 鈥榝unction鈥? {
            //     return process.nextTick(() => {
            //         try {
            //             value.then(resolve, reject)
            //         } catch (error) {
            //             reject(error)
            //         }
            //     })
            // }

            if (this.status === PENDING) {
                this.value = value
                this.status = RESOLVED
                this.onResolvedCallbackArr.forEach(cb => cb())
            }
        }

        const reject = (reason) => {
            if (this.status === PENDING) {
                this.value = reason
                this.status = REJECTED
                this.onRejectedCallbackArr.forEach(cb => cb())
            }
        }

        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }

    then(onResolved, onRejected) {
        onResolved = typeof onResolved === 鈥榝unction鈥?? onResolved : value => value
        onRejected = typeof onRejected === 鈥榝unction鈥?? onRejected : error => { throw error }

        const promise2 = new Promise((resolve, reject) => {
            if (this.status === RESOLVED) {
                setTimeout(() => {
                    try {
                        const x = onResolved(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            }

            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        const x = onRejected(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            }

            if (this.status === PENDING) {
                this.onResolvedCallbackArr.push(() => {
                    setTimeout(() => {
                        try {
                            const x = onResolved(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                })
                this.onRejectedCallbackArr.push(() => {
                    setTimeout(() => {
                        try {
                            const x = onRejected(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                })
            }
        })
        return promise2
    }

    //==============浠ヤ笅闈?Promise/A+ 瑙勮寖涓殑鍐呭==================
    catch(onRejected) {
        return this.then(null, onRejected)
    }

    finally(callback) {
        return this.then(value => {
            return Promise.resolve(callback()).then(() => value)
        }, error => {
            return Promise.resolve(callback()).then(() => { throw error })
        })
    }

    static resolve(value) {
        if (value instanceof Promise) return value

        return new Promise((resolve, reject) => {
            if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
                typeof value.then === 鈥榝unction鈥? {

                process.nextTick(() => {
                    try {
                        value.then(resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            } else {
                resolve(value)
            }
        })
    }

    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }

    static all(promises) {
        return new Promise((resolve, reject) => {

            if (promises == undefined || !promises[Symbol.iterator]) {
                const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
                return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
            }

            if (promises.length === 0) return resolve([])

            let index = 0
            const resultArr = []

            const processValue = (i, value) => {
                resultArr[i] = value
                if (++index === promises.length) {
                    return resolve(resultArr)
                }
            }
            for (let i = 0; i < promises.length; i++) {
                Promise.resolve(promises[i]).then(value => {
                    processValue(i, value)
                }, error => {
                    return reject(error)
                })
            }
        })
    }

    static race(promises) {
        return new Promise((resolve, reject) => {

            if (promises == undefined || !promises[Symbol.iterator]) {
                const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
                return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
            }

            if (promises.length === 0) return

            for (let i = 0; i < promises.length; i++) {
                Promise.resolve(promises[i]).then(value => {
                    return resolve(value)
                }, error => {
                    return reject(error)
                })
            }
        })
    }
}

Promise.defer = Promise.deferred = function () {
    const dfd = {}
    dfd.promise = new Promise((resolve, reject) => {
        dfd.resolve = resolve
        dfd.reject = reject
    })
    return dfd
}

module.exports = Promise

promise-es6

/**
 * ES6瀹炵幇鐨凱romise锛屽湪Promise/A+鍩虹涓婃墿灞曚簡寰堝鍔熻兘锛屾棤娉曢€氳繃涓篜romise/A+鍐欑殑娴嬭瘯
 */

const PENDING = 鈥楶ENDING鈥?const REJECTED = 鈥楻EJECTED鈥?const RESOLVED = 鈥楻ESOLVED鈥?
const resolvePromise = (promise2, x, resolve, reject) => {
    if (promise2 === x) {
        // ES6 瑙勮寖鍐欐硶 鏃犳硶閫氳繃Promise/A+娴嬭瘯
        return reject(鈥榌TypeError: Chaining cycle detected for promise #<Promise>]鈥?
    }

    let called

    if ((typeof x === 鈥榦bject鈥?&& x !== null) || typeof x === 鈥榝unction鈥? {
        try {
            const then = x.then
            if (typeof then === 鈥榝unction鈥? {

                // then.call(x, y => {
                //     if (called) return
                //     called = true
                //     resolvePromise(promise2, y, resolve, reject)
                // }, e => {
                //     if (called) return
                //     called = true
                //     reject(e)
                // })

                // 妯℃嫙ES6鐨勮涓?寮傛璋冪敤thenable鐨則hen鏂规硶)銆傛棤娉曢€氳繃Promise/A+娴嬭瘯
                process.nextTick(() => {
                    then.call(x, y => {
                        if (called) return
                        called = true
                        resolvePromise(promise2, y, resolve, reject)
                    }, e => {
                        if (called) return
                        called = true
                        reject(e)
                    })
                })

            } else {
                resolve(x)
            }
        } catch (error) {
            if (called) return
            called = true
            reject(error)
        }
    } else {
        resolve(x)
    }
}

class Promise {

    constructor(executor) {
        if (typeof executor !== 鈥榝unction鈥? {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }

        this.status = PENDING
        this.value = undefined

        this.onResolvedCallbackArr = []
        this.onRejectedCallbackArr = []

        const resolve = (value) => {
            if (value === this) {
                return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
            }

            if (value instanceof Promise) {
                return value.then(resolve, reject)
            }

            // resolve瑙f瀽thenable瀵硅薄鏄疎S6 Promise鐨勫姛鑳斤紝鏃犳硶閫氳繃Promise/A+娴嬭瘯
            if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
                typeof value.then === 鈥榝unction鈥? {
                return process.nextTick(() => {
                    try {
                        value.then(resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }

            if (this.status === PENDING) {
                this.value = value
                this.status = RESOLVED
                this.onResolvedCallbackArr.forEach(cb => cb())
            }
        }

        const reject = (reason) => {
            if (this.status === PENDING) {
                this.value = reason
                this.status = REJECTED
                this.onRejectedCallbackArr.forEach(cb => cb())
            }
        }

        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }

    then(onResolved, onRejected) {
        onResolved = typeof onResolved === 鈥榝unction鈥?? onResolved : value => value
        onRejected = typeof onRejected === 鈥榝unction鈥?? onRejected : error => { throw error }

        const promise2 = new Promise((resolve, reject) => {
            if (this.status === RESOLVED) {
                process.nextTick(() => {
                    try {
                        const x = onResolved(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }

            if (this.status === REJECTED) {
                process.nextTick(() => {
                    try {
                        const x = onRejected(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }

            if (this.status === PENDING) {
                this.onResolvedCallbackArr.push(() => {
                    process.nextTick(() => {
                        try {
                            const x = onResolved(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    })
                })
                this.onRejectedCallbackArr.push(() => {
                    process.nextTick(() => {
                        try {
                            const x = onRejected(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    })
                })
            }
        })
        return promise2
    }

    //==============浠ヤ笅闈?Promise/A+ 瑙勮寖涓殑鍐呭==================
    catch(onRejected) {
        return this.then(null, onRejected)
    }

    finally(callback) {
        return this.then(value => {
            return Promise.resolve(callback()).then(() => value)
        }, error => {
            return Promise.resolve(callback()).then(() => { throw error })
        })
    }

    static resolve(value) {
        if (value instanceof Promise) return value

        return new Promise((resolve, reject) => {
            if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
                typeof value.then === 鈥榝unction鈥? {

                process.nextTick(() => {
                    try {
                        value.then(resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            } else {
                resolve(value)
            }
        })
    }

    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }

    static all(promises) {
        return new Promise((resolve, reject) => {

            if (promises == undefined || !promises[Symbol.iterator]) {
                const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
                return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
            }

            if (promises.length === 0) return resolve([])

            let index = 0
            const resultArr = []

            const processValue = (i, value) => {
                resultArr[i] = value
                if (++index === promises.length) {
                    return resolve(resultArr)
                }
            }
            for (let i = 0; i < promises.length; i++) {
                Promise.resolve(promises[i]).then(value => {
                    processValue(i, value)
                }, error => {
                    return reject(error)
                })
            }
        })
    }

    static race(promises) {
        return new Promise((resolve, reject) => {

            if (promises == undefined || !promises[Symbol.iterator]) {
                const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
                return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
            }

            if (promises.length === 0) return

            for (let i = 0; i < promises.length; i++) {
                Promise.resolve(promises[i]).then(value => {
                    return resolve(value)
                }, error => {
                    return reject(error)
                })
            }
        })
    }
}

Promise.defer = Promise.deferred = function () {
    const dfd = {}
    dfd.promise = new Promise((resolve, reject) => {
        dfd.resolve = resolve
        dfd.reject = reject
    })
    return dfd
}

module.exports = Promise

promise-comment

/*
Promise 瀹炵幇瑙勮寖 Promise/A+ 鍦板潃: https://promisesaplus.com/

浼樼偣锛氳В鍐冲紓姝ラ棶棰?1. 澶氫釜骞跺彂寮傛璇锋眰锛屽悓鏃惰幏鍙栫粨鏋?-> promise.all
2. 閾惧紡寮傛璇锋眰锛堟伓榄旈噾瀛楀銆佸洖璋冨湴鐙憋級-> promise.then 閾惧紡璋冪敤

缂虹偣锛?1. 鏈韩杩樻槸鍩轰簬鍥炶皟鍑芥暟鐨勫舰寮?2. 鏃犳硶涓柇寮傛澶勭悊缁撴灉

promise寰幆寮曠敤闂锛?    寰幆寮曠敤鍙兘鍙戠敓鍦ㄥ紓姝ユ儏鍐典笅(then 鐨勫弬鏁板嚱鏁颁腑 鎴?瀹氭椂鍣ㄤ腑)銆傛鏃舵瀯閫犲嚱鏁版墠鑳芥墽琛屽畬姣曡幏鍙栧埌褰撳墠promise锛岀劧鍚庡啀寮曠敤锛屽彂鐢熷惊鐜紩鐢?    杩斿洖涓€涓柊鐨刾romise閮戒細鎵ц鏋勯€犲嚱鏁帮紙璋冪敤then鐨勬椂鍊欙級

promise閫掑綊瑙f瀽闂锛?    瑙f瀽promise鍗?璋冪敤 璇romise鐨?then鏂规硶锛屽皢澶栧眰promise鐨剅esolve reject 浣滀负鍐呭眰promise杩斿洖鍚?瑙﹀彂鎵ц鐨?then鏂规硶鐨?鍥炶皟
      then鐨勫弬鏁板嚱鏁拌繑鍥瀙romise浼氶€掑綊瑙f瀽锛岀洿鍒拌繑鍥為潪promise鎴栬reject銆?        搴曞眰鍘熺悊鏄皢then杩斿洖鐨?promise鐨?resolve鍜宺eject 浣滀负鍙傛暟鍑芥暟杩斿洖鐨?promise鐨?then鐨?鍥炶皟锛?        褰撳弬鏁板嚱鏁拌繑鍥炵殑 promise杩斿洖鍚?鎵嶈Е鍙戞墽琛?      鏋勯€犲嚱鏁颁腑鎻愪緵鐨剅esolve鏂规硶浼氶€掑綊瑙f瀽锛岀洿鍒拌繑鍥為潪promise鎴栬reject锛坮eject涓嶄細瑙f瀽promise锛?        搴曞眰鍘熺悊鏄皢鑷繁鍜宺eject浣滀负鍙傛暟promise鐨則hen鐨勫洖璋冿紝褰撳弬鏁皃romise杩斿洖鍚庯紝鎵嶈Е鍙戞墽琛?    鍥犳閫掑綊瑙f瀽鐨勬椂鍊?      鏌愬唴灞傚け璐ュ悗锛屽灞備緷娆¤皟鐢ㄥ叾reject鏂规硶锛屼篃閮借繑鍥炲け璐?      鏈€鍐呭眰鎴愬姛鍚庯紝澶栧眰渚濇璋冪敤鍏秗esolve鏂规硶锛屼篃閮借繑鍥炴垚鍔?    娉ㄥ唽then鍥炶皟
      閫掓帹鐨勬椂鍊欎笉浼氬皢then鐨勫洖璋冩敞鍐屽埌寰换鍔¢槦鍒楀熬閮?      鍥炲綊鐨勬椂鍊欙紝promise鐘舵€佹敼鍙樻墠浼氭敞鍐屽埌寰换鍔¢槦鍒楀熬閮紝鍦ㄤ笅娆″惊鐜墽琛?
promise 寮傚父闂锛?    1. 濡傛灉娌℃湁浼犻€抏xecutor鍑芥暟锛岀洿鎺ユ姏鍑哄紓甯革紝澶栭潰鍙互鍚屾鎹曡幏
    2. 濡傛灉鍦╡xecutor鍑芥暟浣撲腑寮傛浠g爜鎶涘嚭寮傚父锛屽闈㈡棤娉曞悓姝ユ崟鑾凤紝鍙兘鍏ㄥ眬鎹曡幏锛堟垨鑰呭紓姝ヤ唬鐮佽嚜宸辨崟鑾凤紝璋冪敤reject閫氱煡澶栭潰锛?    3. 鍏朵粬鎯呭喌涓媝romise涓嶄細灏嗗紓甯告姏鍒板叏灞€锛岄兘鏄繑鍥炰竴涓け璐ョ殑promise
    4. 濡傛灉鍦╡xecutor鍑芥暟浣撲腑鍚屾浠g爜鎶涘嚭寮傚父
      4.1 鍦╮esolve鎴杛eject涔嬪墠鎶涘嚭鐨勫紓甯革紝琚玹ry-catch鎹曡幏锛岃繑鍥炲け璐ョ殑promise
      4.2 鍦╮esolve鎴杛eject鎺ユ敹鐨勫弬鏁板嚱鏁颁腑鎶涘嚭寮傚父锛岃try-catch鎹曡幏锛岃繑鍥炲け璐ョ殑promise
      4.3 鍦╮esolve鎴杛eject涔嬪悗鎶涘嚭鐨勫紓甯革紝琚玹ry-catch鎹曡幏锛屼笉褰卞搷promise鐨勭姸鎬?    5. 濡傛灉鍦╰hen鍥炶皟鍑芥暟涓姏鍑哄紓甯?      5.1 琚玹hen涓殑try-catch鎹曡幏锛岃繑鍥炲け璐ョ殑promise
    6. thenable瀵硅薄
      6.1 濡傛灉鍦ㄥ叾then鍙傛暟鍑芥暟resolve鍜宺eject涔嬪墠鎶涘紓甯革紝閮戒細琚玹ry-catch鎹曡幏锛岃繑鍥炲け璐ョ殑promise
          e.g. Promise.resolve銆佹瀯閫犲嚱鏁颁腑鐨剅esolve銆乼hen鐨剅esolvePromise
      6.2 濡傛灉鍦ㄥ叾then鍙傛暟鍑芥暟resolve鍜宺eject涔嬪悗鎶涘紓甯革紝浼氳try-catch鎹曡幏锛屼絾鏄笉鏀瑰彉promise鐨勭姸鎬?
promise then浜嬩欢寰幆闂锛?    璋冪敤then灏变細灏唗hen鐨勫弬鏁板嚱鏁版敞鍐屽埌寰换鍔¢槦鍒楁湯灏撅紝鍦ㄤ笅涓€杞簨浠跺惊鐜墠浼氭墽琛岋紙寤惰繜涓€杞墽琛岋級

Promise/A+ 娴嬭瘯闂
    1. 娉ㄦ帀瑙勮寖鏂规硶涓殑鏃ュ織
    2. 娉ㄦ帀闈炶鑼冧腑鐨勫姛鑳斤紙3涓湴鏂癸級
*/

const u = require("../utils")
const log = u.debugGenerator(__filename)

// 鐘舵€侊紙鐢ㄥ父閲忚〃绀猴級
// 1. Promise鏈変笁涓姸鎬侊紝resolved(fulfilled) rejected pending(榛樿鍒濆鐘舵€?
// 2. 涓€鏃︽敼鍙樻棤娉曚慨鏀癸紝鍙湁pending鐘舵€佷笅鎵嶅彲浠ヤ慨鏀?const RESOLVED = 鈥楻ESOLVED鈥?const REJECTED = 鈥楻EJECTED鈥?const PENDING = 鈥楶ENDING鈥?
// 杩欎釜鏂规硶瑕佸吋瀹?鎵€鏈?鍏朵粬搴撳疄鐜扮殑promise锛屼緥濡?bluebird銆乹銆乪s6-promise銆傝繖浜涘簱鍙互鐩镐簰璋冪敤涓昏闈?resolvePromise 鏂规硶鍏煎
const resolvePromise = (promise2, x, resolve, reject) => {

    // 寰幆寮曠敤-鑷繁绛夊緟鑷繁锛坧romise2 鍜?x 寮曠敤鍚屼竴涓璞★級
    if (promise2 === x) {
        log.debug(鈥榩romise.then circular reference鈥?
        // ES6 瑙勮寖鍐欐硶 鏃犳硶閫氳繃Promise/A+娴嬭瘯
        return reject(鈥榌TypeError: Chaining cycle detected for promise #<Promise>]鈥?
        // Promise/A+ 瑙勮寖
        // return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
    }

    let called // 鏍囪锛岄槻姝㈠埆鐨勫簱瀹炵幇鐨刾romise璧版垚鍔熷悗鍙堣蛋澶辫触

    // 涓ユ牸鏍规嵁瑙勮寖鍒ゆ柇锛岀‘淇濆彲浠ュ吋瀹瑰叾浠栧簱瀹炵幇鐨刾romise
    // if (x instanceof Promise) { } // 涓嶈兘鐢ㄨ繖绉嶆柟寮忓垽鏂瓁鏄笉鏄疨romise锛屽洜涓簒鍙兘鏄埆鐨勫簱瀹炵幇鐨凱romise鐨勫疄渚?    if ((typeof x === 鈥榦bject鈥?&& x !== null) || typeof x === 鈥榝unction鈥? {
        // 濡傛灉x鏄璞℃垨鍑芥暟
        try {
            // promise(x)閮芥湁涓€涓猼hen鏂规硶锛屽彇x鐨勫睘鎬hen锛岀湅鏄笉鏄嚱鏁版潵鍒ゆ柇x鏄笉鏄痯romise
            // 閫氳繃 x.then 鍙栧€煎彲鑳戒細鎶ラ敊锛岄渶瑕乼ry-catch (鍙傝€冪ず渚?promise-resolvePromise.js)
            const then = x.then
            if (typeof then === 鈥榝unction鈥? {
                // 鑷虫锛岃涓簒鏄痯romise

                // 涓嶈兘鍐欐垚 x.then锛屽洜涓鸿繖鏍蜂細鍐嶆鍙栧€硷紝鏈夊彲鑳芥姤閿?(鍙傝€冪ず渚?promise-resolvePromise.js)
                // 鐢?call 鏂规硶锛屼繚璇乼hen鏂规硶涓殑THIS鏄渶瑕佽幏鍙栫粨鏋滅殑promise瀹炰緥(x)銆傚鏋滀笉call鍒欐槸window鎴杇lobal
                // 濡傛灉鏄痶henable瀵硅薄锛宼hen 鏂规硶浣撲腑鍙兘浼氭姤閿欙紝浼氳catch鎹曡幏鍒?                // 鏍规嵁鍐呭眰promise(x)鐨勭姸鎬佸拰鍊?鍐冲畾澶栧眰promise2鐨勭姸鎬佸拰鍊?
                // then.call(x,
                //     y => {
                //         //銆愯繖閲岃皟鐢ㄥ埆浜哄疄鐜扮殑promise涓殑then鏂规硶锛屾墽琛岃嚜宸变紶鍏ョ殑鍥炶皟銆?                //         // 鏃犳硶鎺у埗鍒汉鐨勪唬鐮佹墽琛屽嚑涓洖璋冿紝鍙兘鎺у埗鑷繁浼犲叆鐨勫洖璋冿紙娣诲姞鍒ゆ柇锛夐槻姝㈣蛋鎴愬姛鍚庡張璧板け璐?                //         if (called) return
                //         called = true

                //         // 绛?x(promise) 杩斿洖鎴愬姛锛堝€间负y锛夈€傚垯鎵цx鐨則hen鏂规硶鐨勭涓€涓弬鏁板嚱鏁帮紙杩欓噷浼犲叆鐨勫洖璋冿級
                //         // 鍗虫墽琛屽綋鍓峵hen鏂规硶杩斿洖promise2鐨剅esolve鏂规硶锛屼娇褰撳墠then杩斿洖涓€涓垚鍔熺殑promise2锛屽€间负x(promise)鐨勬垚鍔熺粨鏋測

                //         // resolve(y) 浣嗘槸涓轰簡瑙e喅杩斿洖promise(x)鎴愬姛鍙堣繑鍥瀙romise鐨勭幇璞?y杩樻槸涓€涓猵romise)锛岃繖閲岄渶瑕侀€掑綊瑙f瀽

                //         log.debug(`before resolvePromise recursion, y is 鈥?{y}鈥榒)
                //         // 绗竴涓弬鏁颁粛鐒舵槸鏈€澶栧眰then杩斿洖鐨刾romise2锛堢敤鏉ヤ繚璇佷笉鍙戠敓寰幆寮曠敤锛?resolve銆乺eject 涔熸槸promise2鐨?                //         //   褰搚(promise)杩斿洖鍚庯紝璋冪敤promise2鐨剅esolve鎴杛eject
                //         // 褰撴渶缁坹涓嶆槸promise,鍦ㄣ€愬嚭鍙?鎴?銆戠粨鏉燂紝鎴杫杩斿洖澶辫触锛屽洖褰掑埌杩欓噷锛屽祵濂楃殑resolvePromise渚濇缁撴潫
                //         resolvePromise(promise2, y, resolve, reject)
                //         log.debug(`end resolvePromise recursion, y is 鈥?{y}鈥榒)
                //     },
                //     e => {
                //         // 闃叉璧版垚鍔熷悗鍙堣蛋澶辫触
                //         if (called) return
                //         called = true

                //         // 鍚岀悊锛屽鏋?x(promise) 杩斿洖澶辫触锛屽垯褰撳墠then杩斿洖鐨刾romise2杩斿洖澶辫触锛屽€间负x(promise)鐨勫け璐ュ師鍥?                //         // promise(x)澶辫触鍙堣繑鍥瀙romise锛堝嵆e鏄竴涓猵romise锛夛紝涓嶅啀閫掑綊瑙f瀽锛岀洿鎺ュ皢鏈€鍚庣殑promise浣滀负澶辫触鍘熷洜杩斿洖
                //         reject(e)
                //     })


                // 鏍规嵁娴嬭瘯缁撴灉锛?.promise-then.js 鏈€鍚庝竴涓祴璇曠敤渚嬶級锛岄渶瑕佸紓姝ユ墽琛宼henable鐨則hen鏂规硶銆備娇鐢?process.nextTick锛堜釜浜虹悊瑙o級
                // 1. process.nextTick 浜嬩欢灏嗗湪褰撳墠闃舵鐨勫熬閮ㄦ墽琛岋紙涓嬫浜嬩欢寰幆涔嬪墠锛?                // 2. process.nextTick 灏嗕簨浠剁淮鎶ゅ湪 nextTickQueue 涓?                //    瀵逛簬promise鏉ヨ锛屾病鍔犱箣鍓嶏紝绔嬪嵆璋冪敤then灏嗗洖璋冩斁鍏?nextTickQueue 涓紱鍔犱簡涔嬪悗锛屽厛灏嗗then鐨勮皟鐢ㄦ斁鍏?nextTickQueue 涓?                //    鎵ц浼氬悗锛屽啀灏嗗洖璋冩斁鍏?nextTickQueue 涓€傚嵆瀵逛簬nextTickQueue鏉ヨ锛屽洖璋冧細寤惰繜鎵ц锛屼絾鏈€缁堥兘鍦ㄥ綋鍓嶉樁娈垫墽琛岋紝
                //    瀵逛簨浠跺惊鐜暣浣撴潵璇存病鏈夊お澶х殑褰卞搷
                // 3. 鏃犳硶閫氳繃Promise/A+ 娴嬭瘯锛侊紒锛?
                process.nextTick(() => {
                    then.call(x,
                        y => {
                            //銆愯繖閲岃皟鐢ㄥ埆浜哄疄鐜扮殑promise涓殑then鏂规硶锛屾墽琛岃嚜宸变紶鍏ョ殑鍥炶皟銆?                            // 鏃犳硶鎺у埗鍒汉鐨勪唬鐮佹墽琛屽嚑涓洖璋冿紝鍙兘鎺у埗鑷繁浼犲叆鐨勫洖璋冿紙娣诲姞鍒ゆ柇锛夐槻姝㈣蛋鎴愬姛鍚庡張璧板け璐?                            if (called) return
                            called = true

                            // 绛?x(promise) 杩斿洖鎴愬姛锛堝€间负y锛夈€傚垯鎵цx鐨則hen鏂规硶鐨勭涓€涓弬鏁板嚱鏁帮紙杩欓噷浼犲叆鐨勫洖璋冿級
                            // 鍗虫墽琛屽綋鍓峵hen鏂规硶杩斿洖promise2鐨剅esolve鏂规硶锛屼娇褰撳墠then杩斿洖涓€涓垚鍔熺殑promise2锛屽€间负x(promise)鐨勬垚鍔熺粨鏋測

                            // resolve(y) 浣嗘槸涓轰簡瑙e喅杩斿洖promise(x)鎴愬姛鍙堣繑鍥瀙romise鐨勭幇璞?y杩樻槸涓€涓猵romise)锛岃繖閲岄渶瑕侀€掑綊瑙f瀽

                            log.debug(`before resolvePromise recursion, y is 鈥?{y}鈥榒)
                            // 绗竴涓弬鏁颁粛鐒舵槸鏈€澶栧眰then杩斿洖鐨刾romise2锛堢敤鏉ヤ繚璇佷笉鍙戠敓寰幆寮曠敤锛?resolve銆乺eject 涔熸槸promise2鐨?                            //   褰搚(promise)杩斿洖鍚庯紝璋冪敤promise2鐨剅esolve鎴杛eject
                            // 褰撴渶缁坹涓嶆槸promise,鍦ㄣ€愬嚭鍙?鎴?銆戠粨鏉燂紝鎴杫杩斿洖澶辫触锛屽洖褰掑埌杩欓噷锛屽祵濂楃殑resolvePromise渚濇缁撴潫
                            resolvePromise(promise2, y, resolve, reject)
                            log.debug(`end resolvePromise recursion, y is 鈥?{y}鈥榒)
                        },
                        e => {
                            // 闃叉璧版垚鍔熷悗鍙堣蛋澶辫触
                            if (called) return
                            called = true

                            // 鍚岀悊锛屽鏋?x(promise) 杩斿洖澶辫触锛屽垯褰撳墠then杩斿洖鐨刾romise2杩斿洖澶辫触锛屽€间负x(promise)鐨勫け璐ュ師鍥?                            // promise(x)澶辫触鍙堣繑鍥瀙romise锛堝嵆e鏄竴涓猵romise锛夛紝涓嶅啀閫掑綊瑙f瀽锛岀洿鎺ュ皢鏈€鍚庣殑promise浣滀负澶辫触鍘熷洜杩斿洖
                            reject(e)
                        })
                })

            } else {
                // x 涓嶆槸 promise锛堟槸涓櫘閫氬璞℃垨鏅€氬嚱鏁帮級锛屼緥濡傦細{then:123}
                // 閫掑綊鍑哄彛1銆愮粓缁撹€?銆?                log.debug(`the property 鈥榯hen鈥?of 鈥榵鈥?is not a function, x is 鈥?{x}鈥榒)
                resolve(x)
            }
        } catch (error) {
            // x.then 鍙栧€煎嚭閿?            // thenable 鏂规硶浣撲腑锛屾墽琛屼簡浼犲叆鐨?resolve 鍙傛暟鍑芥暟鍚庯紝鍐嶆姏寮傚父锛屼篃浼氳繘鍏ヨ繖閲?            log.error(`thenable error 鈥?{error}鈥榒)

            // 闃叉璧版垚鍔熷悗鍙堣蛋澶辫触
            if (called) return
            called = true

            reject(error)
        }
    } else {
        // 濡傛灉x涓嶆槸瀵硅薄鎴栧嚱鏁帮紝鐩存帴杩斿洖鎴愬姛鐘舵€佺殑promise2
        // 閫掑綊鍑哄彛2銆愮粓缁撹€?銆?        log.debug(`x is not a promise, x is ${x}`)
        resolve(x)
    }
}

log.debug(鈥?===== my promise ======鈥?

class Promise {

    // 1. 鍒涘缓绫荤殑瀹炰緥锛岄渶瑕佺瓑鏋勯€犲嚱鏁颁腑鐨勪唬鐮佸叏閮ㄦ墽琛屽畬姣曪紝鎵嶈兘鎷垮埌鍊?    //  1.1 濡傛灉resolve鎴杛eject鏄紓姝ヨ皟鐢紝鍒欐瀯閫犲嚱鏁版墽琛屽畬姣曡繑鍥?PENDING 鐘舵€佺殑promise
    // 2. THIS
    //  2.1 鏋勯€犲嚱鏁颁腑鐨凾HIS鎸囦唬褰撳墠瀹炰緥瀵硅薄
    constructor(executor) {

        // executor 鎵ц鍣?        // 1. 鏋勯€犲嚱鏁板繀椤讳紶鍏ヤ竴涓弬鏁帮紝绫诲瀷鏄嚱鏁?        // 2. 濡傛灉涓嶆槸鍑芥暟锛屽垯鐩存帴鎶涚被鍨嬮敊璇?
        if (typeof executor !== "function") {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }

        this.status = PENDING         // 鐘舵€侊細鍒濆鐘舵€佷负 pending
        this.value = undefined        // 鍊? 淇濆瓨鎴愬姛鐨勭粨鏋滄垨澶辫触鐨勫師鍥?
        this.onResolvedCallbacks = [] // 瀛樻斁鐘舵€佸彉涓烘垚鍔熸椂鐨勫洖璋?        this.onRejectedCallbacks = [] // 瀛樻斁鐘舵€佸彉涓哄け璐ユ椂鐨勫洖璋?
        // 1. 璋冪敤 resolve 鏂规硶
        //   1.1 濡傛灉value鏄痯romise锛屽垯寮傛锛堣皟鐢級鎵ц锛屼綔涓?promise 鎴愬姛鍚巘hen鐨勬垚鍔熷洖璋冩墽琛?        //   1.2 濡傛灉value闈瀙romise锛屽垯鍚屾锛堣皟鐢級鎵ц锛屽皢value璧嬪€肩粰THIS锛堝鏋滄斁鍒板畾鏃跺櫒涓紝灞炰簬寮傛璋冪敤锛屼絾鏄皟鐢ㄥ悗鏄珛鍗冲悓姝ユ墽琛岀殑锛?        // 2. THIS
        //   2.1 璋冪敤 resolve 鏂规硶鐨勬椂鍊欐病鏈夋寚鏄庤皝璋冪敤鐨勶紝鍥犳杩欓噷鐨凾HIS闇€瑕佹槑纭寚鍚戝綋鍓嶅疄渚嬶紙浣跨敤绠ご鍑芥暟,THIS鏄瀯閫犲嚱鏁颁腑鐨凾HIS锛?        const resolve = (value) => {
            // resolve涓娇鐢ㄦā鏉垮瓧绗︿覆锛屾棤娉曢€氳繃Promise/A+娴嬭瘯
            log.debug(`call resolve, status is 鈥?{this.status}鈥? value is 鈥?{value}鈥榒)

            // 寮傛resolve(鈥榯his鈥?锛屼細瀵艰嚧寰幆寮曠敤-鑷繁绛夊緟鑷繁
            if (value === this) {
                // 杩斿洖涓€涓け璐ョ殑promise
                return reject(new TypeError(鈥楥haining cycle detected for promise #<Promise>鈥?)
            }

            // 杩欓噷涓嶇敤鍏煎鍏朵粬鐗堟湰鐨刾romise锛屽彧鏄嚜宸辩殑鍔熻兘锛堥潪瑙勮寖涓殑锛?            if (value instanceof Promise) {
                // 閫掑綊瑙f瀽promise锛岀洿鍒皏alue闈瀙romise
                // 鏄紓姝ユ墽琛岋紙娑夊強鍒皌hen锛?                // 璋冪敤鍐呴儴then鏂规硶锛屼笉浼氭姏鍑哄紓甯?                return value.then(resolve, reject)
            }

            // resolve瑙f瀽thenable瀵硅薄鏄疎S6鐨勫姛鑳斤紝鏃犳硶閫氳繃Promise/A+娴嬭瘯
            if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
                typeof value.then === 鈥榝unction鈥? {
                // thenable 瀵硅薄
                // 璋冪敤鍐呴儴then鏂规硶锛屽叾鍥炶皟鏄紓姝ユ墽琛岀殑锛岃€岃皟鐢╰henable瀵硅薄涓璽hen鏂规硶锛屽叾鍥炶皟鏄悓姝ョ殑(璋冪敤thenable.then灏变細鎵ц)
                // 鍥犳杩欓噷闇€瑕佸湪璋冪敤鐨勬椂鍊欏紓姝ワ紙寰换鍔★級
                // 璋冪敤鍐呴儴鐨則hen鏂规硶锛屾棤娉曞仛鎵嬭剼銆傝€宼henable瀵硅薄涓彲浠ュthen鏂规硶鍋氭墜鑴氾紝鍥犳杩欓噷瑕佹斁鍒皌ry-catch涓?                return process.nextTick(() => {
                    try {
                        value.then(resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }

            // 鍙湁 pending 鐘舵€佸彲浠ヤ慨鏀圭姸鎬佸拰鍊硷紙纭繚resolve鍜宺eject鍙細鎵ц涓€娆★級
            if (this.status === PENDING) {
                this.value = value
                this.status = RESOLVED
                this.onResolvedCallbacks.forEach(cb => cb())
            }

            // JSON.stringify() 涓㈠け娉ㄥ唽鐨勫嚱鏁?            log.debug("------promise is------", this) // 鎵撳嵃resolve鎵€灞炵殑promise
        }

        // 1. 璋冪敤 reject鏂规硶锛屽悓姝ユ墽琛岋紙濡傛灉鏀惧埌瀹氭椂鍣ㄤ腑锛屽睘浜庡紓姝ヨ皟鐢紝浣嗘槸璋冪敤鍚庢槸绔嬪嵆鍚屾鎵ц鐨勶級
        //   1.1 涓嶇reason灞炰簬浠€涔堢被鍨嬪€硷紝閮藉師鏍疯祴鍊肩粰THIS
        //   1.2 濡傛灉reason鏄痯romise锛宺eject涓嶄細杩涜瑙f瀽锛岀洿鎺ヨ祴鍊肩粰THIS
        const reject = (reason) => {
            log.debug(`call reject, status is 鈥?{this.status}鈥? reason is 鈥?{reason}鈥榒)
            // 鍙湁 pending 鐘舵€佸彲浠ヤ慨鏀圭姸鎬佸拰鍊硷紙纭繚resolve鍜宺eject鍙細鎵ц涓€娆★級
            if (this.status === PENDING) {
                this.value = reason
                this.status = REJECTED
                this.onRejectedCallbacks.forEach(cb => cb())
            }
        }

        // 1. executor鍑芥暟锛岀珛鍗冲悓姝ユ墽琛?        //   1.1 鍚屾浠g爜鎶ラ敊锛屽彲浠ユ崟鑾峰埌寮傚父
        //   1.2 寮傛浠g爜鎶ラ敊锛屾棤娉曟崟鑾凤紙褰撳紓姝ヤ唬鐮佹墽琛岀殑鏃跺€欙紝鎹曡幏寮傚父鐨勫嚱鏁板凡缁忓嚭鏍堜簡锛?        // 2. executor 涓粯璁ゆ彁渚?resolve reject 鏂规硶
        //   2.1 璋冪敤 resolve 灏嗙姸鎬佸彉涓?resolved锛屽€间负鎴愬姛缁撴灉銆傝Е鍙憈hen鐨勬垚鍔熷洖璋冩墽琛?        //   2.2 璋冪敤 reject 灏嗙姸鎬佸彉涓?rejected锛屽€间负澶辫触鍘熷洜銆傝Е鍙憈hen鐨勫け璐ュ洖璋冩墽琛?        //   2.3 涓嶆槸闈欐€佹柟娉曪紝涓嶆槸瀹炰緥鏂规硶锛屼篃涓嶆槸绉佹湁鏂规硶锛屽氨鏄竴涓湪鏋勯€犲嚱鏁颁腑瀹氫箟鐨勬柟娉?        //   2.4 鏄竴涓棴鍖呭嚱鏁帮紝鍦ㄦ瀯閫犲嚱鏁颁腑瀹氫箟锛屽湪鍒涘缓promise鐨勫湴鏂规墽琛?
        //   2.5 璋冪敤 resolve鎴杛eject 涓嶄細缁撴潫executor鍑芥暟鐨勬墽琛岋紝鍗冲悗闈㈢殑浠g爜渚濈劧浼氭墽琛屻€?        //       涓€鑸涓猴紝璋冪敤 resolve鎴杛eject鍚庯紝promise鐨勪綔鐢ㄥ氨瀹屾垚浜嗭紝鍚庣画鎿嶄綔搴旇鏀惧埌then鏂规硶涓紝
        //       鍥犳涓€鑸湪璋冪敤 resolve鎴杛eject鍓嶅姞涓妑eturn
        //   2.6 resolve 鍜?reject 鐨勫弬鏁板彧鑳芥槸鍊肩被鍨嬶紝濡傛灉鏄釜琛ㄨ揪寮忥紙new鏋勯€犲嚱鏁?鎴?鏅€氬嚱鏁癧璋冪敤]锛夛紝
        //         浼氬厛灏嗗叾鍦╡xecutor鍑芥暟浣撲腑鎵ц锛屽緱鍒拌〃杈惧紡鐨勮繑鍥炲€煎啀浼犵粰 resolve 鎴?reject 鎵ц
        //         濡傛灉鍦ㄦ墽琛岃繃绋嬩腑鎶ラ敊锛屽彲浠ヨexecutor鐨則ry-catch鎹曡幏
        // 3. 鑷畾涔?        //   3.1 鎴愬姛杩樻槸澶辫触锛堜粈涔堟儏鍐典笅璋冪敤 resolve/reject锛夌敱鐢ㄦ埛鍐冲畾
        //   3.2 鎴愬姛鐨勭粨鏋滃拰澶辫触鐨勫師鍥狅紝鐢辩敤鎴峰喅瀹?        try {
            executor(resolve, reject)
        } catch (error) {
            log.error(`catch executor error: 鈥?{error}鈥榒)
            reject(error)
        }
    }

    // then
    // 1. Promise 蹇呴』鍏锋湁then鏂规硶
    //   1.1 then鏂规硶闇€瑕佺敤鎴蜂紶鍏ヤ袱涓弬鏁板嚱鏁帮紙鍥炶皟鍑芥暟锛夛紝绗竴涓槸鐘舵€佸彉涓烘垚鍔熸椂瑙﹀彂鎵ц(鎺ユ敹鎴愬姛鐨勭粨鏋?銆愭垚鍔熷洖璋冦€戯紝
    //       绗簩涓槸鐘舵€佸彉涓哄け璐ユ椂瑙﹀彂鎵ц锛堟帴鏀跺け璐ョ殑鍘熷洜锛夈€愬け璐ュ洖璋冦€戙€傘€愪袱涓弬鏁板嚱鏁板彧鑳借Е鍙戞墽琛屼竴涓€?    //   1.2 濡傛灉鏌愪釜鍙傛暟鍑芥暟娌℃湁浼犻€掞紝鍒欎細浣跨敤榛樿鍙傛暟鍑芥暟
    //   1.3 then鏂规硶鍚屾鎵ц锛屼絾鏄紶鍏ョ殑涓や釜鍙傛暟鍑芥暟锛堝洖璋冿級鏄紓姝ユ墽琛?    //         ES6鐨凱romise涓璽hen灞炰簬寰换鍔★紝鍏朵粬Promise搴撳彲鑳芥槸瀹忎换鍔★紙bluebird锛?    //         鏃犳硶鑷繁瀹炵幇涓€涓井浠诲姟锛屽彧鑳借皟鐢ㄥ涓荤幆澧冩彁渚涚殑API
    //   1.4 then鏂规硶鍦ㄨ皟鐢ㄥ弬鏁板嚱鏁版椂浼氫紶鍏モ€楾HIS鈥?璋冪敤then鐨刾romise瀹炰緥)鐨勫€硷紝鍗冲弬鏁板嚱鏁板彲浠ユ嬁鍒板綋鍓峱romise鐨勫€?    // 2. then鏂规硶 杩斿洖涓€涓€愭柊銆戠殑promise
    //   2.1 then 鏂规硶鐨勬墽琛岃繃绋嬬被浼兼墽琛屾瀯閫犲嚱鏁帮紝澶勭悊瀹屽洖璋冨嚱鏁帮紙娉ㄥ唽鍒板井浠诲姟闃熷垪鎴栨坊鍔犲埌寰呮墽琛岄槦鍒楋級涔嬪悗锛岀珛鍗宠繑鍥?PENDING 鐘舵€佺殑promise
    //       缁х画鎵ц鍚庣画鍚屾浠g爜锛堝洜姝ら摼寮忚皟鐢ㄤ細鍚屾鎵цthen鏂规硶锛屽畬鍚庡啀鎵цthen鏂规硶鐨勫洖璋冿級
    // 3. then鏂规硶 杩斿洖promise鐨勭姸鎬?鍙?閾惧紡璋冪敤 promise杩斿洖鍊肩殑浼犻€掕鍒欙細
    //   3.1 闇€瑕佸湪鍙傛暟鍑芥暟涓敤return鏄庣‘鎸囧畾杩斿洖鍊硷紝鍚﹀垯then鏂规硶榛樿杩斿洖涓€涓垚鍔熺殑promise锛屽€兼槸undefined锛屼紶鍏ヤ笅涓€涓猼hen鐨勬垚鍔熷洖璋冧腑
    //   3.2 濡傛灉鍙傛暟鍑芥暟杩斿洖鐨勬槸銆愭櫘閫氬€笺€戯紙闈瀙romise瀹炰緥銆乼henable瀵硅薄銆佸紓甯革紝鍗虫櫘閫氬璞°€佹暟瀛椼€佸瓧绗︿覆銆乽ndefined锛堥粯璁わ級锛?    //       鍒檛hen鏂规硶杩斿洖涓€涓垚鍔熺殑promise锛屽€兼槸璇ユ櫘閫氬€硷紝浼犲叆涓嬩竴涓猼hen鐨勬垚鍔熷洖璋冧腑
    //   3.3 濡傛灉鍙傛暟鍑芥暟銆愭姏鍑哄紓甯搞€戯紝浼氳then鍐呴儴鐨則ry-catch鎹曡幏
    //       鍒檛hen鏂规硶杩斿洖涓€涓け璐ョ殑promise锛屽€兼槸寮傚父鍘熷洜锛屼紶鍏ヤ笅涓€涓猼hen鐨勫け璐ュ洖璋冧腑
    //   3.4 濡傛灉鍙傛暟鍑芥暟杩斿洖涓€涓€恜romise瀹炰緥銆戯紝鍒欒promise瀹炰緥鐨勭姸鎬佷細鍐冲畾褰撳墠then鏂规硶杩斿洖promise鐨勭姸鎬侊紝浠庤€屽喅瀹氫笅涓€涓猼hen鍙傛暟鍑芥暟鐨勬墽琛屾儏鍐?    //     3.4.1 濡傛灉鍙傛暟鍑芥暟杩斿洖涓€涓垚鍔熺殑promise锛屽垯褰撳墠then涔熻繑鍥炰竴涓垚鍔熺殑promise锛屽€兼槸鍙傛暟鍑芥暟杩斿洖promise鐨勬垚鍔熺粨鏋滐紝浼犲叆涓嬩竴涓猼hen鐨勬垚鍔熷洖璋冧腑  
    //     3.4.2 濡傛灉鍙傛暟鍑芥暟杩斿洖涓€涓け璐ョ殑promise锛屽垯褰撳墠then涔熻繑鍥炰竴涓け璐ョ殑promise锛屽€兼槸鍙傛暟鍑芥暟杩斿洖promise鐨勫け璐ュ師鍥狅紝浼犲叆涓嬩竴涓猼hen鐨勫け璐ュ洖璋冧腑
    // 4. 閿欒澶勭悊
    //   4.1 濡傛灉璺濈鑷繁鏈€杩戠殑then娌℃湁浼犻€掔浜屼釜鍙傛暟鍑芥暟锛屽垯鎵句笅涓€涓猼hen鎴朿atch
    // 5. THIS
    //   5.1 then鏂规硶涓殑THIS鏄皟鐢╰hen鐨刾romise瀹炰緥

    then(onResolved, onRejected) {
        // 鏂规硶涓殑THIS鏄皟鐢╰hen鐨刾romise瀹炰緥
        log.info(`call then, promise status is ${this.status}`)

        // 鍒ゆ柇鏄惁浼犻€掑弬鏁颁互鍙婁紶閫掔殑鏄笉鏄嚱鏁?        // onResolved = typeof onResolved === 鈥榝unction鈥?? onResolved : value => { return value }
        onResolved = typeof onResolved === 鈥榝unction鈥?? onResolved : v => v
        // onRejected = typeof onRejected === 鈥榝unction鈥?? onRejected : err => { throw err }
        onRejected = typeof onRejected === 鈥榝unction鈥?? onRejected : e => { throw e }

        // 鎳掗€掑綊锛屾瘡娆¤皟鐢ㄥ氨new涓€涓柊鐨刾romise
        const promise2 = new Promise((resolve, reject) => {

            // then鏂规硶鍚屾鎵ц锛堝垽鏂槸鍚屾鐨勶級锛屽洖璋冨嚱鏁板紓姝ユ墽琛?            if (this.status === RESOLVED) {
                // then涓洖璋冨嚱鏁板紓姝ユ墽琛岋紝鍙互鐢?setTimeout 鎴?process.nextTick 妯℃嫙瀹炵幇銆愬彧鑳界敤涓€绉嶏紝涓嶈兘娣风敤銆?                // ES6 瑙勮寖涓?then 鏄井浠诲姟锛岃繖閲屾棤娉曡嚜宸卞疄鐜颁竴涓井浠诲姟锛屽彧鑳借皟鐢ㄥ涓荤幆澧冩彁渚涚殑API锛坧rocess.nextTick锛?
                // then鏂规硶鍚屾鎵ц鍒拌繖閲岋紝鍒涘缓鍖垮悕鍑芥暟鐨勬椂鍊欙紝promise2 杩樻病鏈夊畾涔夛紙绛夋瀯閫犲嚱鏁颁腑鐨勪唬鐮佸叏閮ㄦ墽琛屽畬姣曪紝鎵嶈兘鎷垮埌promise2锛?                // 鏋勯€犲嚱鏁拌繕娌℃湁鎵ц瀹岋紝浣嗘槸鍦ㄦ瀯閫犲嚱鏁颁腑灏变娇鐢ㄤ簡瀹炰緥锛屽洜姝ゅ尶鍚嶅嚱鏁扮殑鎵ц涓€瀹氭槸寮傛鐨勶紝鎵嶈兘鍦ㄦ墽琛屾椂鎷垮埌瀹炰緥

                // setTimeout(() => {
                //     try {
                //         const x = onResolved(this.value)
                //         log.debug("RESOLVED:then return x =", x)
                //         resolvePromise(promise2, x, resolve, reject)
                //     } catch (error) {
                //         reject(error)
                //     }
                // }, 0)

                process.nextTick(() => {
                    try {
                        // 鍥炶皟鍑芥暟寮傛鎵ц锛屽闈xecutor鐨則ry-catch鏃犳硶鎹曡幏鍒板紓甯革紝鍥犳闇€瑕佸湪婧愬ご鎹曡幏
                        const x = onResolved(this.value)
                        // 濡傛灉x鏄櫘閫氬€硷紝鍙互鐩存帴 resolve(x)
                        log.debug("RESOLVED:then return x =", x)

                        // 閫掑綊瑙f瀽鍥炶皟鍑芥暟鐨勮繑鍥炲€紉锛屽喅瀹歵hen杩斿洖鐨刾romise2鐨勭姸鎬?                        // 濡傛灉x鏄痯romise锛岃皟鐢ㄨpromise鐨則hen鏂规硶鏃讹紝浼犻€掔殑涓や釜鍙傛暟鍑芥暟灏辨槸褰撳墠then杩斿洖promise2鐨別xecutor涓彁渚涚殑resolve reject
                        //   1. 濡傛灉璇romise杩斿洖鎴愬姛锛屽垯璋冪敤褰撳墠then杩斿洖promise2鐨剅esolve鏂规硶锛屼娇褰撳墠then杩斿洖涓€涓垚鍔熺殑promise2
                        //   2. 濡傛灉璇romise杩斿洖澶辫触锛屽垯璋冪敤褰撳墠then杩斿洖promise2鐨剅eject鏂规硶锛屼娇褰撳墠then杩斿洖涓€涓け璐ョ殑promise2
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        // 鍙傛暟鍑芥暟寮傚父锛宼hen杩斿洖涓€涓け璐ョ殑promise2
                        log.error("RESOLVED: catch error:", error)
                        reject(error)
                    }
                })
            }

            if (this.status === REJECTED) {

                // setTimeout(() => {
                //     try {
                //         const x = onRejected(this.value)
                //         log.debug("REJECTED:then return x =", x)
                //         resolvePromise(promise2, x, resolve, reject)
                //     } catch (error) {
                //         reject(error)
                //     }
                // }, 0)

                process.nextTick(() => {
                    try {
                        const x = onRejected(this.value)
                        // 濡傛灉x鏄櫘閫氬€硷紝鍙互鐩存帴 resolve(x)
                        log.debug("REJECTED:then return x =", x)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        log.error("REJECTED: catch error:", error)
                        reject(error)
                    }
                })
            }

            // 濡傛灉 executor 閲岄潰寮傛璋冪敤resolve鎴杛eject锛屽垯璋冪敤then鏂规硶鏃讹紝褰撳墠promise鏄痯ending鐘舵€?            // 濡傛灉褰撳墠鐘舵€佹槸 pending锛岄渶瑕佺敤鍙戝竷璁㈤槄妯″紡锛屽垯灏嗕紶鍏ョ殑鍥炶皟鍑芥暟淇濆瓨璧锋潵锛岀◢鍚庢墽琛宺esolve鎴杛eject鏀瑰彉鐘舵€佹椂鍐嶈Е鍙戞墽琛?            // 鍚屼竴涓猵romise鍙互澶氭璋冪敤 then 鏂规硶锛屽洜姝や細鏈夊涓洖璋冨嚱鏁帮紝闇€瑕佺敤鏁扮粍淇濆瓨
            if (this.status === PENDING) {

                // AOP
                this.onResolvedCallbacks.push(() => {
                    // 涓嶆槸绔嬪嵆鎵ц锛屽綋鎵ц澶栭潰鐨勫尶鍚嶅嚱鏁扮殑鏃跺€欙紝鎵嶄細鎵ц
                    // do other things...

                    // setTimeout(() => {
                    //     try {
                    //         const x = onResolved(this.value)
                    //         log.debug("PENDING->RESOLVED:then return x =", x)
                    //         resolvePromise(promise2, x, resolve, reject)
                    //     } catch (error) {
                    //         reject(error)
                    //     }
                    // }, 0)

                    process.nextTick(() => {
                        try {
                            const x = onResolved(this.value)
                            // 濡傛灉x鏄櫘閫氬€硷紝鍙互鐩存帴 resolve(x)
                            log.debug("PENDING->RESOLVED:then return x =", x)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            log.error("PENDING->RESOLVED: catch error:", error)
                            reject(error)
                        }
                    })
                })

                this.onRejectedCallbacks.push(() => {

                    // setTimeout(() => {
                    //     try {
                    //         const x = onRejected(this.value)
                    //         log.debug("PENDING->REJECTED:then return x =", x)
                    //         resolvePromise(promise2, x, resolve, reject)
                    //     } catch (error) {
                    //         reject(error)
                    //     }
                    // }, 0)

                    process.nextTick(() => {
                        try {
                            const x = onRejected(this.value)
                            // 濡傛灉x鏄櫘閫氬€硷紝鍙互鐩存帴 resolve(x)
                            log.debug("PENDING->REJECTED:then return x =", x)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            log.error("PENDING->REJECTED: catch error:", error)
                            reject(error)
                        }
                    })
                })
            }
        })
        return promise2
    }

    //=============================================浠ヤ笅闈濸romise/A+ 瑙勮寖===============================================
    // 杩斿洖涓€涓柊鐨刾romise锛屾牴鎹?onRejected 鐨勮繑鍥炵粨鏋滃喅瀹氳繑鍥瀙romise鐨勭姸鎬?    catch(onRejected) {
        // THIS鎸囦唬璋冪敤catch鐨刾romise瀹炰緥
        return this.then(null, onRejected)
    }

    // node>10 
    // 琛ㄧず鍓嶉潰鐨刾romise鏃犺鎴愬姛杩樻槸澶辫触閮戒細鎵цfinally鏂规硶
    //   褰撴棤璁哄浣曞繀椤昏澶勭悊涓€涓€昏緫鐨勬椂鍊欎娇鐢紝濡傛灉杩斿洖鎴愬姛鐨刾romise涓嶅奖鍝嶆暣涓猼hen閾剧殑缁撴灉
    // callback
    //  1. 璋冪敤callback涓嶄細浼犻€掑弬鏁帮紙鏃犳硶鎷垮埌鍓嶉潰promise鐨勮繑鍥炲€硷級
    //  2. callback鏈€缁堝湪then鐨勫弬鏁板嚱鏁颁腑琚皟鐢?    //  3. callback杩斿洖涓€涓猵romise锛堝鏋滀笉鏄垯鐢≒romise.resolve杞崲涓簆romise锛夛紝涓斾細绛夊緟杩欎釜promise杩斿洖
    // finally鍊间紶閫掕鍒?    //  璋冪敤then鏂规硶杩斿洖涓€涓猵romise锛屾牴鎹甤allback鐨勬墽琛岀粨鏋滃喅瀹氳嚜宸辩殑鐘舵€佸拰鍊?    //   1. 濡傛灉callback杩斿洖鐨刾romise鎴愬姛锛屽垯finally杩斿洖鎴愬姛鐨刾romise锛屽€间负鍓嶉潰promise鐨勬垚鍔熺粨鏋滐紝浼犻€掍笅鍘伙紙閬靛惊 then 鐨勯摼寮忚皟鐢ㄥ師鐞嗭級
    //   2. 濡傛灉callback杩斿洖鐨刾romise澶辫触锛屽垯finally杩斿洖澶辫触鐨刾romise锛屽€间负callback杩斿洖promise鐨勫け璐ュ師鍥狅紝鍙栦唬骞朵紶閫掍笅鍘伙紙閬靛惊 then 鐨勯摼寮忚皟鐢ㄥ師鐞嗭級
    //   3. 濡傛灉callback鎵ц鎶ラ敊锛屽垯琚綋鍓峵hen鍥炶皟鐨則ry-catch鎹曡幏锛宖inally杩斿洖澶辫触鐨刾romise锛屽€间负鎶ラ敊鍘熷洜锛屽彇浠e苟浼犻€掍笅鍘?    finally(callback) {
        log.info(`call finally, promise is ${JSON.stringify(this)}`)
        return this.then(value => {
            log.debug("finally: previous promise is resolved")
            // 濡傛灉鍓嶉潰promise鎴愬姛锛屽垯杩涘叆杩欓噷

            // 鎵ц椤哄簭锛氬湪鍥炶皟鍑芥暟涓細
            //  1.鎵ц callback()锛岃繑鍥炰竴涓€?            //  2.鎵ц Promise.resolve()锛岃繑鍥炰竴涓猵romise
            //  3.鎵ц then鏂规硶锛屽鐞嗗洖璋?鈥?)=>value鈥?
            //  4.杩斿洖涓€涓?PENDING 鐘舵€佺殑promise銆傦紙姝ゆ椂瀵瑰闈㈢殑then鏂规硶鏉ヨ灏辨槸绗竴涓弬鏁板洖璋冭繑鍥炲€紉鏄竴涓猵romise锛岀户缁В鏋愶級
            return Promise.resolve(callback()).then(() => value)
        }, err => {
            log.debug("finally: previous promise is rejected")
            // 濡傛灉鍓嶉潰鐨刾romise澶辫触锛屽垯杩涘叆杩欓噷
            return Promise.resolve(callback()).then(() => { throw err })
        })
    }

    // 灏嗗綋鍓嶅€艰浆鎹负promise瀵硅薄锛歅romise.resolve([value])
    // 鍙傛暟:
    //  1. 鏄竴涓猵romise瀹炰緥锛屽垯鐩存帴鍘熸牱杩斿洖
    //  2. 鏄竴涓猼henable瀵硅薄锛屽垯寮傛璋冪敤鍏秚hen鏂规硶,鍐冲畾resolve杩斿洖promise鐨勭姸鎬?    //    2.1 Promise.resolve([thenable]) 鍙兘浼氳繑鍥炰竴涓け璐ョ殑promise
    //  3. 涓嶆槸thenable瀵硅薄鎴杙romise瀹炰緥锛屽垯杩斿洖涓€涓柊鐨勬垚鍔熺殑promise锛屽€间负璇ュ弬鏁?    //  4. 涓嶄紶鍙傛暟锛岃繑鍥炰竴涓柊鐨勬垚鍔熺殑promise锛屽€间负undefined
    static resolve(value) {
        // 涓嶅鐞嗗吋瀹?        if (value instanceof Promise) {
            // 鍘熸牱杩斿洖
            return value
        }
        return new Promise((resolve, reject) => {
            if (((typeof value === 鈥榦bject鈥?&& value !== null) || typeof value === 鈥榝unction鈥? &&
                typeof value.then === 鈥榝unction鈥? {
                // thenable 瀵硅薄
                // 璋冪敤鍐呴儴then鏂规硶锛屽叾鍥炶皟鏄紓姝ユ墽琛岀殑锛岃€岃皟鐢╰henable瀵硅薄涓璽hen鏂规硶锛屽叾鍥炶皟鏄悓姝ョ殑(璋冪敤thenable.then灏变細鎵ц)
                // 鍥犳杩欓噷闇€瑕佸湪璋冪敤鐨勬椂鍊欏紓姝ワ紙寰换鍔★級
                // 璋冪敤鍐呴儴鐨則hen鏂规硶锛屾棤娉曞仛鎵嬭剼銆傝€宼henable瀵硅薄涓彲浠ュthen鏂规硶鍋氭墜鑴氾紝鍥犳杩欓噷瑕佹斁鍒皌ry-catch涓?                process.nextTick(() => {
                    try {
                        value.then(resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            } else {
                return resolve(value)
            }
        })
    }

    // 灏嗗綋鍓嶅€艰浆鎹负涓€涓け璐ョ殑promise瀵硅薄锛歅romise.reject([value])
    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }

    // 鍙傛暟锛氬疄鐜癷terator鎺ュ彛鐨勫彲杩唬瀵硅薄锛堟暟缁勩€佸瓧绗︿覆锛?    //  1. 濡傛灉鍙傛暟涓嶅瓨鍦ㄦ垨鑰呬笉鍙凯浠o紝杩斿洖涓€涓け璐ョ殑promise锛屽€间负绫诲瀷閿欒
    //  2. 濡傛灉鍙凯浠e璞℃垚鍛樹负绌猴紝杩斿洖涓€涓垚鍔熺殑promise锛屽€间负绌烘暟缁?    //  3. 濡傛灉鍙凯浠e璞℃垚鍛樹笉鏄痯romise锛屽垯璋冪敤 Promise.resolve 灏嗗叾鍙樹负涓€涓猵romise
    // 杩斿洖promise鐨勭姸鎬侊細鐢辨墍鏈夊彲杩唬瀵硅薄鐨勬垚鍛橈紙promise锛夌殑杩斿洖鐘舵€佸喅瀹?    //  1. 鎵€鏈夋垚鍛榩romise閮借繑鍥炴垚鍔燂紝鍒檃ll杩斿洖涓€涓垚鍔熺殑promise锛屽€间负鎵€鏈夋垚鍛榩romise杩斿洖鍊肩粍鎴愮殑鏁扮粍锛堟寜鎴愬憳椤哄簭鎺掑簭锛?    //  2. 鍙涓€涓垚鍛榩romise杩斿洖澶辫触锛屽垯all杩斿洖涓€涓け璐ョ殑promise锛屽€间负绗竴涓け璐ョ殑鎴愬憳promise鐨勫け璐ュ師鍥?    //  3. 濡傛灉鎴愬憳promise鑷韩瀹氫箟浜哻atch鏂规硶锛岄偅涔堝畠琚玶ejected鏃朵細琚嚜韬畾涔夌殑catch鎹曡幏锛?    //     骞惰繑鍥炰竴涓柊鐨刾romise锛堢敤杩欎釜鏂皃romise鐘舵€佷唬鏇胯鎴愬憳promise鐘舵€侊級
    static all(promises) {
        return new Promise((resolve, reject) => {

            if (promises == undefined || !promises[Symbol.iterator]) {
                const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
                return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
            }

            if (promises.length === 0) return resolve([])

            let index = 0
            const resultArr = []

            function processValue(i, value) {
                resultArr[i] = value
                if (++index === promises.length) {
                    resolve(resultArr)
                }
            }
            for (let i = 0; i < promises.length; i++) {
                //promises[i] 鍙兘鏄櫘閫氬€硷紝鐢?Promise.resolve 鍖呬竴灞傦紝纭繚閮芥槸promise
                Promise.resolve(promises[i]).then((value) => {
                    processValue(i, value)
                }, (err) => {
                    // 鏈変竴涓け璐ュ垯缁撴潫寰幆
                    return reject(err)
                })
            }
        })
    }

    // 鍙傛暟锛氬疄鐜癷terator鎺ュ彛鐨勫彲杩唬瀵硅薄锛堟暟缁勩€佸瓧绗︿覆锛?    //  1. 濡傛灉鍙傛暟涓嶅瓨鍦ㄦ垨鑰呬笉鍙凯浠o紝杩斿洖涓€涓け璐ョ殑promise锛屽€间负绫诲瀷閿欒
    //  2. 濡傛灉鍙凯浠e璞℃垚鍛樹负绌猴紝銆愯繑鍥炰竴涓狿ENDING 鐘舵€佺殑promise銆?    //  3. 濡傛灉鍙凯浠e璞℃垚鍛樹笉鏄痯romise锛屽垯璋冪敤 Promise.resolve 灏嗗叾鍙樹负涓€涓猵romise
    // 杩斿洖promise鐨勭姸鎬侊細
    //  1. 鍙涓€涓垚鍛榩romise杩斿洖锛屽垯race杩斿洖鐩稿悓鐘舵€佺殑promise
    static race(promises) {
        return new Promise((resolve, reject) => {

            if (promises == undefined || !promises[Symbol.iterator]) {
                const preReason = promises === undefined ? `${promises}` : `${typeof promises} ${promises}`
                return reject(new TypeError(`${preReason} is not iterable (cannot read property Symbol(Symbol.iterator))`))
            }

            if (promises.length === 0) return

            for (let i = 0; i < promises.length; i++) {
                Promise.resolve(promises[i]).then((value) => {
                    return resolve(value)
                }, (err) => {
                    return reject(err)
                });
            }
        });
    }
}

// 娴嬭瘯鍏ュ彛
// Promise鐨勫欢杩熷璞★紝娴嬭瘯鐨勬椂鍊欎細璋冪敤杩欎釜鍑芥暟
Promise.defer = Promise.deferred = function () {
    const dfd = {}
    dfd.promise = new Promise((resolve, reject) => {
        dfd.resolve = resolve
        dfd.reject = reject
    })
    return dfd
}

module.exports = Promise

娴嬭瘯

鏇磋缁嗙殑娴嬭瘯鐢ㄤ緥鍙傝€價epo https://github.com/lfp1024/promise

resolve 瑙f瀽 promise

  • resolve(promise) 鍙互閫掑綊瑙f瀽锛岀敱鍐呭眰promise鐨勭姸鎬佸喅瀹氬灞俻romise鐨勭姸鎬?/li>
  • reject(promise) 涓嶄細閫掑綊瑙f瀽锛屽灞俻romise鐩存帴杩斿洖澶辫触锛屽け璐ュ師鍥犳槸promise
var p1 = new Promise(function (resolve, reject) {
    resolve(new Promise(res => res(鈥榬esolve鈥?));
});

var p2 = new Promise(function (resolve, reject) {
    // 灏唕esolve瀹炲弬promise鐨勭姸鎬佸彉涓鸿嚜宸辩殑鐘舵€侊紝灏嗗疄鍙俻romise鐨勫€煎彉涓鸿嚜宸辩殑鍊?    resolve(new Promise((res, rej) => { rej(鈥榬eject鈥? }));
});

var p3 = new Promise(function (resolve, reject) {
    reject(new Promise(res => res(鈥榬esolve鈥?));
});

p1.then(
    function fulfilled(value) { console.log(鈥榩1 fulfilled: 鈥?+ value); },
    function rejected(err) { console.log(鈥榩1 rejected: 鈥?+ err); }
);

p2.then(
    function fulfilled(value) { console.log(鈥榩2 fulfilled: 鈥?+ value); },
    function rejected(err) { console.log(鈥榩2 rejected: 鈥?+ err); }
);

p3.then(
    function fulfilled(value) { console.log(鈥榩3 fulfilled: 鈥?+ value); },
    function rejected(err) { console.log(鈥榩3 rejected: 鈥?+ err); }
);

// 杈撳嚭缁撴灉锛?// p3 rejected: [object Object]
// p1 fulfilled: resolve
// p2 rejected: reject 


/*
瑙i噴锛?// 鍚屾浠g爜鎵ц
p1 鐨?resolve 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?p2 鐨?resolve 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?p3 鐨?reject 褰撳墠鎵ц鏍堜腑鍚屾鎵ц锛屽皢 p3.then 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?
// 涓嬩竴杞惊鐜?p1 鐨?resolve 鎵ц锛屽皢 p1.then 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?p2 鐨?resolve 鎵ц锛屽皢 p2.then 娉ㄥ唽鍒颁笅涓€杞惊鐜墽琛?p3.then 鎵ц锛岃緭鍑?=> p3 rejected: [object Object]

// 涓嬩竴杞惊鐜?p1.then 鎵ц锛岃緭鍑?=> p1 fulfilled: resolve
p2.then 鎵ц锛岃緭鍑?=> p2 rejected: reject
 */

resolve 瑙f瀽 thenable瀵硅薄

  • ES6 鐨剅esolve鍙互瑙f瀽thenable瀵硅薄銆備笖thenable.then灞炰簬寰换鍔?/li>
  • thenable.then鏂规硶涓殑鍙傛暟鍑芥暟鐨勬墽琛屾儏鍐典細鍐冲畾褰撳墠promise鐨勭姸鎬?/li>
console.log("--script start--")
let obj = {
    then: function (onResolved, onRejected) {
        console.log("寮傛鎵цthenable then")
        onResolved(鈥樻垚鍔熷暒鈥?
    }
}
setTimeout(() => {
    console.log("setTimeout") 
}, 0);
let p1 = new Promise(function (resolve, reject) {
    console.log("1")
    resolve(obj);
    console.log("2")
});
p1.then(res=>{
    console.log("promise then")
}) 
console.log("p1 =", p1)
setTimeout(() => {
    console.log("p1 = ", p1) 
}, 0); 
console.log("--script end--") 


// 浠庤緭鍑洪『搴忓彲浠ョ湅鍑鸿皟鐢╰henable鐨則hen鏂规硶灞炰簬寰换鍔?// --script start--
// 1
// 2
// p1 =  Promise { <pending> }
// --script end--
// 寮傛鎵цthenable then 
// promise then
// setTimeout
// p1 =  Promise { 鈥樻垚鍔熷暒鈥?}

// 濡傛灉鏄畯浠诲姟锛屽垯杈撳嚭椤哄簭搴斾负锛堣皟鐢╮esolve涔嬪墠锛宲1.then灏氭湭娉ㄥ唽鍒颁簨浠堕槦鍒椾腑锛?// --script start--
// 1
// 2
// p1 =  Promise { <pending> }
// --script end--
// setTimeout
// 寮傛鎵цthenable then
// promise then
// p1 =  Promise { 鈥樻垚鍔熷暒鈥?}

then 閫掑綊瑙f瀽 promise

  • then 浼氶€掑綊瑙f瀽鍏跺洖璋冨嚱鏁拌繑鍥炵殑promise銆傛渶鍐呭眰promise鐨勭姸鎬佸喅瀹氬灞倀hen杩斿洖promise鐨勭姸鎬?/li>
let p = new Promise((resolve, reject) => {
    resolve(1)
})

// [resolve(promise)]-------------------------------------------------

// 3灞俻romise锛氭渶澶栧眰p1锛屼腑闂村眰p2(then鐨勭涓€涓洖璋冭繑鍥炵殑promise)锛屾渶鍐呭眰p3锛?绉掑悗鎴愬姛鎴栧け璐ワ級
let p1 = p.then(value => {
    // then鐨勫弬鏁板嚱鏁拌繑鍥炰竴涓?new Promise
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // resolve 鍙堣繑鍥炰竴涓猵romise锛岄€掑綊瑙f瀽
            resolve(new Promise((resolve, reject) => {
                setTimeout(() => {
                    // 鏈€鍐呭眰promise璋冪敤resolve鎴愬姛涔嬪悗锛屼細鎵ц鍏秚hen鐨勭涓€涓洖璋冿紝鍗虫墽琛屼腑闂村眰p2鐨剅esolve
                    // resolve("success") 
                    // 鏈€鍐呭眰promise璋冪敤reject澶辫触涔嬪悗锛屼細鎵ц鍏秚hen鐨勭浜屼釜鍥炶皟锛屽嵆鎵ц涓棿灞俻2鐨剅eject
                    reject("fail")
                }, 1000);
            }))
        }, 1000);
    })
})
// 澶栭潰鎯宠鑾峰彇褰撳墠then杩斿洖promise鐨勭粨鏋滐紝杩樻槸瑕佽皟鐢ㄥ綋鍓峵hen杩斿洖promise鐨則hen鏂规硶
p1.then(res => {
    console.log("褰撳墠then杩斿洖promise鐨勭粨鏋?", res)   // 褰撳墠then杩斿洖promise鐨勭粨鏋? success
}, err => {
    console.log("褰撳墠then杩斿洖promise鐨勫師鍥?", err)   // 褰撳墠then杩斿洖promise鐨勫師鍥? fail
})

// [reject(promise)]-------------------------------------------------

let promise = new Promise((resolve, reject) => {
    resolve(1)
})
let promise2 = promise.then(value => {
    // then鐨勫弬鏁板嚱鏁拌繑鍥炰竴涓?new Promise
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            // reject 鍙堣繑鍥炵殑涓€涓猵romise锛屼笉鍐嶉€掑綊瑙f瀽锛堜絾鏄細鎵цnew琛ㄨ揪寮忥紝鎵ц瀹屽悗绔嬪嵆杩斿洖涓€涓?PENDING 鐘舵€佺殑promise锛?            reject(new Promise((resolve, reject) => {
                console.log("鎵ц")
                setTimeout(() => {
                    resolve("success")
                }, 1000);
            }))
        }, 1000);
    })
})
// 澶栭潰鎯宠鑾峰彇褰撳墠then杩斿洖promise鐨勭粨鏋滐紝杩樻槸瑕佽皟鐢ㄥ綋鍓峵hen杩斿洖promise鐨則hen鏂规硶
promise2.then(res => {
    console.log("褰撳墠then杩斿洖promise鐨勭粨鏋?", res)
}, err => {
    console.log("褰撳墠then杩斿洖promise鐨勫師鍥?", err) // 褰撳墠then杩斿洖promise鐨勫師鍥? Promise { <pending> }
})

then 瑙f瀽 thenable 瀵硅薄

  • then瑙f瀽 thenable 寮傛璋冪敤鍏秚hen 鏂规硶
console.log("--script start--")
let obj = {
    then: function (onResolved, onRejected) {
        console.log("寮傛鎵цthenable then")
        onResolved(鈥樻垚鍔熷暒鈥?
        // onRejected(鈥樺け璐ュ暒鈥?
        // throw Error("Oops!")
    }
}
setTimeout(() => {
    console.log("setTimeout")
}, 0)

let p = Promise.resolve(鈥榦k鈥?
let p1 = p.then(res => {
    console.log("p2 then")
    return obj
})

let p2 = Promise.resolve(鈥榦k2鈥?
let p3 = p2.then(res => {
    console.log("p3 then")
    return 
})

console.log("p1 =", p1)

setTimeout(() => {
    console.log("p1 = ", p1)
}, 0)
console.log("--script end--")

// 杈撳嚭锛?// --script start--
// p1 = Promise { <pending> }
// --script end--
// p2 then
// p3 then
// 寮傛鎵цthenable then
// setTimeout
// p1 =  Promise { 鈥樻垚鍔熷暒鈥?}

// 濡傛灉涓嶆槸寮傛璋冪敤锛岄『搴忔槸锛?// --script start--
// p1 = Promise { <pending> }
// --script end--
// p2 then
// 寮傛鎵цthenable then
// p3 then
// setTimeout
// p1 =  Promise { 鈥樻垚鍔熷暒鈥?}

let fs = require(鈥榝s鈥? // 闇€姹傛槸璇诲彇涓€涓枃浠惰幏鍙栬矾寰勶紝鐒跺悗鍐嶇户缁鍙栧唴瀹?// 褰撳墠璺緞涓嬫湁涓や釜鏂囦欢 name.txt 鍜?age.txt銆俷ame.txt 鍐呭鏄?age.txt銆俛ge.txt 鍐呭鏄?27銆?// 鍏堣鍙?name.txt 鎷垮埌 age.txt锛屽啀璇诲彇 age.txt 鍐呭 fs.readFile(鈥?/name.txt鈥? 鈥榰tf-8鈥? (err, data) => { if (err) { // 閿欒澶勭悊... } console.log("data = ", data) fs.readFile(data, 鈥榰tf-8鈥? (err, data) => { if (err) { // 閿欒澶勭悊... } console.log("data = ", data) }) }) function readFileSync(filePath) { return new Promise((res, rej) => { fs.readFile(filePath, 鈥榰tf-8鈥? (err, data) => { if (err) return rej(err) return res(data) }) }) } readFileSync(鈥?/name.txt鈥?.then((data) => { console.log(鈥樿幏鍙栧埌鏁版嵁鈥? data) return readFileSync(data) }).then((data) => { console.log(鈥樿幏鍙栧埌鏁版嵁鈥? data) }, (err) => { console.log(鈥樺け璐モ€? err) }) /* 鐢?setTimeout 瀹炵幇then鐨勫紓姝ヨ皟鐢紙瀹忎换鍔★級锛岃窡es6鎵ц椤哄簭涓嶅悓 杈撳嚭缁撴灉锛?data = age.txt data = 27 鑾峰彇鍒版暟鎹?age.txt 鑾峰彇鍒版暟鎹?27 鍒嗘瀽锛? // 绗竴杞? fs.readFile 娣诲姞涓€涓畯浠诲姟1锛堣鍙栧埌鏁版嵁涔嬪悗瑙﹀彂锛?readFileSync 娣诲姞涓€涓畯浠诲姟2锛堣鍙栧埌鏁版嵁涔嬪悗瑙﹀彂锛?// 绗簩杞?璇诲彇鍒版暟鎹? 瀹忎换鍔?鎵ц锛岃緭鍑?>data = age.txt锛屾坊鍔犲畯浠诲姟3 瀹忎换鍔?鎵ц锛屾坊鍔犲畯浠诲姟4锛坱hen锛?// 绗笁杞?瀹忎换鍔?鎵ц锛岃緭鍑?>data = 27 // 绗洓杞?瀹忎换鍔?鎵ц锛岃緭鍑?>鑾峰彇鍒版暟鎹?age.txt锛屾坊鍔犲畯浠诲姟5 // 绗簲杞?瀹忎换鍔?鎵ц锛屾坊鍔犲畯浠诲姟6锛坱hen锛?// 绗叚杞?瀹忎换鍔?鎵ц锛岃緭鍑?>鑾峰彇鍒版暟鎹?27 */ /* 鎹㈢敤 process.nextTick 鏉ュ疄鐜板垯鎵ц椤哄簭鐩稿悓 杈撳嚭缁撴灉锛?data = age.txt 鑾峰彇鍒版暟鎹?age.txt data = 27 鑾峰彇鍒版暟鎹?27 鍒嗘瀽锛?// 绗竴杞? fs.readFile 娣诲姞涓€涓畯浠诲姟1锛堣鍙栧埌鏁版嵁涔嬪悗瑙﹀彂锛?readFileSync 娣诲姞涓€涓畯浠诲姟2锛堣鍙栧埌鏁版嵁涔嬪悗瑙﹀彂锛?// 绗簩杞?璇诲彇鍒版暟鎹? 瀹忎换鍔?鎵ц锛岃緭鍑?>data = age.txt锛屾坊鍔犲畯浠诲姟3 瀹忎换鍔?鎵ц锛屾坊鍔犲井浠诲姟1锛坱hen锛?// 绗笁杞?寰换鍔?鎵ц锛岃緭鍑?>鑾峰彇鍒版暟鎹?age.txt锛屾坊鍔犲畯浠诲姟4 // 绗洓杞?瀹忎换鍔?鎵ц锛岃緭鍑?>data = 27 // 绗簲杞?瀹忎换鍔?鎵ц锛屾坊鍔犲井浠诲姟2锛坱hen锛?// 绗叚杞?寰换鍔?鎵ц锛岃緭鍑?>鑾峰彇鍒版暟鎹?27 */

Promise.resolve 瑙f瀽 promise

  • Promise.resolve 瑙f瀽promise
  • Promise.reject 涓嶈В鏋恜romise
var p1 = new Promise(function (resolve, reject) {
    resolve(Promise.resolve(鈥榬esolve鈥?);
});

var p2 = new Promise(function (resolve, reject) {
    resolve(Promise.reject(鈥榬eject鈥?);
});

var p3 = new Promise(function (resolve, reject) {
    reject(Promise.resolve(鈥榬esolve鈥?);
});

p1.then(
    function fulfilled(value) { console.log(鈥榩1 fulfilled: 鈥?+ value); },
    function rejected(err) { console.log(鈥榩1 rejected: 鈥?+ err); }
);

p2.then(
    function fulfilled(value) { console.log(鈥榩2 fulfilled: 鈥?+ value); },
    function rejected(err) { console.log(鈥榩2 rejected: 鈥?+ err); }
);

p3.then(
    function fulfilled(value) { console.log(鈥榩3 fulfilled: 鈥?+ value); },
    function rejected(err) { console.log(鈥榩3 rejected: 鈥?+ err); }
);

// p3 rejected: [object Promise]
// p1 fulfilled: resolve
// p2 rejected: reject 

https://promisesaplus.com/
https://github.com/YvetteLau/Blog/issues/2


以上是关于鏍规嵁 Promise/A+ 鍜?ES6 瑙勮寖锛屽疄鐜?Promise 婧愮爜锛堥檮璇︾粏娉ㄩ噴鍜屾祴璇曪級的主要内容,如果未能解决你的问题,请参考以下文章

鍓嶇涔嬭矾锛氱敤 Angular 瑙勮寖鏉ョ害鏉熷洟闃?git 鎻愪氦

鑵捐 Git 瑙勮寖鍑虹倝锛屽啓缁欏紑鍙戣€呯殑 Git 鎸囧崡!

jqGrid鏍规嵁鏁版嵁鍔ㄦ€佽缃畆owList

jeasyUI DataGrid 鏍规嵁灞忓箷瀹藉害鑷€傚簲

鏍规嵁榧犳爣绉诲叆绉诲嚭鏂瑰悜锛屽疄鐜癶over鏁堟灉

绗洓绔?闈㈠悜瀵硅薄