JS Asynchronous Advancement 5: Promesa manuscrita

Nuestra Promesa manuscrita implementa principalmente las siguientes funciones

  • Inicializar y llamada asíncrona

  • luego atrapa la llamada en cadena

  • API .resolve .reject .all .race (implementa la API de promesa básica)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MyPromise</title>
</head>
<body>
    <h1>MyPromise</h1>

    <script src="./MyPromise.js"></script>
    <script>
        const p1 = new MyPromise((resolve, reject) => {
            // resolve(100)
            // reject('错误信息...')
            setTimeout(() => {
                resolve(100)
            }, 1000)
        })

        // const p11 = p1.then(data1 => {
        //     console.log('data1', data1)
        //     return data1 + 1
        // })
        // const p12 = p11.then(data2 => {
        //     console.log('data2', data2)
        //     return data2 + 2
        // })
        // const p13 = p12.catch(err => console.error(err))

        const p2 = MyPromise.resolve(200)
        const p3 = MyPromise.resolve(300)
        const p4 = MyPromise.reject('错误信息...')
        // const p5 = MyPromise.all([p1, p2, p3]) // 传入 promise 数组,等待所有的都 fulfilled 之后,返回新 promise ,包含前面所有的结果
        // p5.then(result => console.log('all result', result))
        const p6 = MyPromise.race([p1, p2, p3]) // 传入 promise 数组,只要有一个 fulfilled 即可返回
        p6.then(result => console.log('race result', result))

    </script>
</body>
</html>
复制代码

Fundamentos de las promesas

  1. Promise es una clase

  2. Cuando se ejecuta la clase Promise, pasará una función ejecutora, que se ejecutará inmediatamente.

  3. Las promesas tienen tres estados.

    • Pendiente
    • cumplido
    • Rechazado
  4. El estado de una Promesa no se puede cambiar una vez que se determina, y el estado solo se puede determinar mediante

    • Pendiente => Cumplido
    • Pendiente => Rechazado
  5. El cambio de estado se modifica mediante los métodos de resolución y rechazo.

  6. Lo que el método entonces hace internamente es emitir un juicio

    • Si está en estado Cumplido, ejecute una devolución de llamada exitosa
    • Si está en estado Rechazado, ejecute la devolución de llamada fallida
  7. Encadenar promesas requiere devolver una instancia de Promise en el método then

Código

/**
 * @description MyPromise
 * @author 双越
 */

class MyPromise {
    state = 'pending' // 状态,'pending' 'fulfilled' 'rejected'
    value = undefined // 成功后的值
    reason = undefined // 失败后的原因

    resolveCallbacks = [] // pending 状态下,存储成功的回调
    rejectCallbacks = [] // pending 状态下,存储失败的回调

    constructor(fn) {
        const resolveHandler = (value) => {
            if (this.state === 'pending') {
                this.state = 'fulfilled'
                this.value = value
                this.resolveCallbacks.forEach(fn => fn(this.value))
            }
        }

        const rejectHandler = (reason) => {
            if (this.state === 'pending') {
                this.state = 'rejected'
                this.reason = reason
                this.rejectCallbacks.forEach(fn => fn(this.reason))
            }
        }

        try {
            fn(resolveHandler, rejectHandler)
        } catch (err) {
            rejectHandler(err)
        }
    }

    then(fn1, fn2) {
        fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
        fn2 = typeof fn2 === 'function' ? fn2 : (e) => e

        if (this.state === 'pending') {
            const p1 = new MyPromise((resolve, reject) => {
                this.resolveCallbacks.push(() => {
                    try {
                        const newValue = fn1(this.value)
                        resolve(newValue)
                    } catch (err) {
                        reject(err)
                    }
                })

                this.rejectCallbacks.push(() => {
                    try {
                        const newReason = fn2(this.reason)
                        reject(newReason)
                    } catch (err) {
                        reject(err)
                    }
                })
            })
            return p1
        }

        if (this.state === 'fulfilled') {
            const p1 = new MyPromise((resolve, reject) => {
                try {
                    const newValue = fn1(this.value)
                    resolve(newValue)
                } catch (err) {
                    reject(err)
                }
            })
            return p1
        }

        if (this.state === 'rejected') {
            const p1 = new MyPromise((resolve, reject) => {
                try {
                    const newReason = fn2(this.reason)
                    reject(newReason)
                } catch (err) {
                    reject(err)
                }
            })
            return p1
        }
    }

    // 就是 then 的一个语法糖,简单模式
    catch(fn) {
        return this.then(null, fn)
    }
}

MyPromise.resolve = function (value) {
    return new MyPromise((resolve, reject) => resolve(value))
}
MyPromise.reject = function (reason) {
    return new MyPromise((resolve, reject) => reject(reason))
}

MyPromise.all = function (promiseList = []) {
    const p1 = new MyPromise((resolve, reject) => {
        const result = [] // 存储 promiseList 所有的结果
        const length = promiseList.length
        let resolvedCount = 0

        promiseList.forEach(p => {
            p.then(data => {
                result.push(data)

                // resolvedCount 必须在 then 里面做 ++
                // 不能用 index
                resolvedCount++
                if (resolvedCount === length) {
                    // 已经遍历到了最后一个 promise
                    resolve(result)
                }
            }).catch(err => {
                reject(err)
            })
        })
    })
    return p1
}

MyPromise.race = function (promiseList = []) {
    let resolved = false // 标记
    const p1 = new Promise((resolve, reject) => {
        promiseList.forEach(p => {
            p.then(data => {
                if (!resolved) {
                    resolve(data)
                    resolved = true
                }
            }).catch((err) => {
                reject(err)
            })
        })
    })
    return p1
}

复制代码

Supongo que te gusta

Origin juejin.im/post/7078325423460843551
Recomendado
Clasificación