美文网首页
自定义Promise

自定义Promise

作者: 麦西的西 | 来源:发表于2020-12-23 22:33 被阅读0次

Promise是什么

Promise是异步编程的一种解决方案。
具体表达:
语法上来说,Promise是一个构造函数
功能上来说,Promsie对象用来封装一个异步操作并获取其结果

为什么要用Promise

  1. 指定回调函数的方式更加灵活
    回调函数:必须在启动异步任务前指定
    Promise: 启动异步任务,返回Promise对象,给Promise对象绑定回调函数(可以在异步任务结束后执行)
  2. 支持链式调用,解决回调地狱问题。
    回调地狱:不便于阅读,不便于异常处理
    终极解决方案:async...await(完全没有回调函数)

Promise的常用方法

Promise(excutor) // 构造函数
Promise.prototype.then(onResolved, onRejected)
Promise.prototype.catch(onRejected)
Promise.resolve(value)
Promise.reject(reason)
Promise.all(promises)
Promise.race(promises)

Promise的几个关键问题

  1. 抛出异常,pending会变成rejected
  2. 一个Promise指定多个成功、失败的回调,都会调用
  3. Promise.then()返回的Promise对象的结果由什么决定?
    1> 简单表达,由then()指定的回调函数执行结果决定
    2> 详细表达
    a. 如果抛出异常,新Promise变为rejected,reason为抛出的异常
    b. 如果返回的是非Promise的任意值,新Promise变为resolved,value为返回值。
    c. 如果返回的是另一个新Promise,此Promise的结果就会成为新Promise的结果。
  4. 如何中断Promise链?
    返回一个pending状态的Promise对象
  5. Promise异常传透?
    1> 使用then链式调用的时候,可以在最后指定失败的回调
    2> 前面任何操作出了异常,都会传到最后失败的回调处理。

自定义Promise实现

/**
 * 自定义Promise
 */

 (function(window) {
    const PENDING = 'pending'
    const RESOLVED = 'resolved'
    const REJECTED = 'rejected'

    /**
     * 构造函数
     * @param {function} excutor 执行器函数,有两个函数类型的参数:resolved, rejected
     */
    function Promise(excutor) {
        const self = this
        self.status = PENDING
        self.data = undefined // 用来保存Promise的结果
        self.callbacks = [] // 用来保存回调函数对象数组,每一项的结构为{ onResolved, onRejected }

        function resolve(value) {
            if (self.status !== PENDING) { // Promise只能执行一次
                return
            }
            self.status = RESOLVED
            self.data = value
            if (self.callbacks.length > 0) { // 如果回调函数对象数组不为空,则异步执行每一项的onResolved方法
                setTimeout(() => {
                    self.callbacks.forEach(callbackObj => {
                        callbackObj.onResolved(value)
                    })
                })
            }
        }

        function reject(reason) {
            if (self.status !== PENDING) {
                return
            }
            self.status = REJECTED
            self.data = reason
            if (self.callbacks.length > 0) {
                setTimeout(() => {
                    self.callbacks.forEach(callbackObj => {
                        callbackObj.onRejected(reason)
                    })
                })
            }
        }

        try {
            excutor(resolve, reject) // 一旦创建,立即执行
        } catch (err) { // 如果出现异常,则将该异常作为失败的结果
            reject(err)
        }
    }

    /**
     * then()方法,返回一个新Promise, 新Promise的执行结果取决于上一个Promise的返回值
     * 1. 如果抛出异常,新Promise的执行结果rejected, reason为抛出的异常
     * 2. 如果返回值是Promise, 新Promise的执行结果为上一个Promise的执行结果
     * 3. 如果返回值是非Promise, 新Promise的执行结果resolved, value为返回值
     * @param {function} onResolved Promise执行成功的回调,异步回调,接收一个参数value(Promise执行成功的结果)
     * @param {function} onRejected Promise执行失败的回调,异步回调,接收一个参数reason(Promise执行失败的结果)
     */
    Promise.prototype.then = function(onResolved, onRejected) {
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
        const self = this
        return new Promise((resolve, reject) => {
            function handle(callback) {
                try {
                    let result = callback(self.data)
                    if (result instanceof Promise) {
                        result.then(resolve, reject)
                    } else {
                        resolve(result)
                    }
                } catch (err) {
                    reject(err)
                }
            }
            if (self.status === RESOLVED) {
                setTimeout(() => {
                    handle(onResolved)
                })
            } else if (self.status === REJECTED) {
                setTimeout(() => {
                    handle(onRejected)
                })
            } else if (self.status === PENDING) {
                self.callbacks.push({
                    onResolved: () => handle(onResolved),
                    onRejected: () => handle(onRejected)
                })
            }
        })
    }

    /**
     * catch()方法,返回一个Promise
     * @param {function} onRejected Promise执行失败的回调,异步回调,接收一个参数reason(Promise执行失败的结果)
     */
    Promise.prototype.catch = function(onRejected) {
        return Promise.then(undefined, onRejected)
    }

    /**
     * resolve()方法,返回一个Promise
     * 1. 若value为Promise, 则返回Promise的执行结果为value的执行结果
     * 2. 若value为非Promise, 则返回一个执行结果为value的成功Promise 
     * @param {any} value 
     */
    Promise.resolve = function(value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(resolve, reject)
            } else {
                resolve(value)
            }
        })
    }

    /**
     * reject()方法,返回一个指定结果为reason的失败的Promise
     * @param {any} reason 
     */
    Promise.reject = function(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }

    /**
     * 返回一个Promise
     * 1. 有一个失败,结果为失败的结果
     * 2. 都成功,结果为所有promise结果的数组
     * @param {array} promises 
     */
    Promise.all = function(promises) {
        let resultArr = new Array(promises.length)
        let count = 0
        return new Promise((resolve, reject) => {
            promises.forEach((promise, index) => {
                Promise.resolve(promise).then(
                    value => {
                        count++
                        resultArr[index] = value
                        if (count === promises.length) {
                            resolve(resultArr)
                        }
                    },
                    reason => {
                        reject(reason)
                    }
                )
            })
        })
    }

    /**
     * 返回一个Promise, 结果为最先执行完的那个Promise的结果
     * @param {array} promises 
     */
    Promise.race = function(promises) {
        return new Promise((resolve, reject) => {
            promises.forEach(promise => {
                Promise.resolve(promise).then(resolve, reject)
            })
        })
    }

    window.Promise = Promise // 向外暴露Promise
 })(window)



参考资料:尚硅谷Promise教程(promise前端进阶必学)

相关文章

  • 总结

    自定义事件 拖拽 promise

  • [iOS][OC] 看 BRYSerialAnimationQu

    背景 上文 《自定义 Promise 处理串行的异步操作》 分析了串行的异步操作的自定义 Promise 处理。P...

  • 宏观看Promise

    自定义Promise实现,来了解他的运行原理

  • 【React】JS异步执行工具 Promise

    使用Promise 实现刷新页面、业务代码的先后执行 自定义封装(方便调用) 自定义调用

  • 手写Promise(自定义Promise)

    首先我们得先理解Promise工作的机制,其实Promise就是一个构造函数 它的内部有三个状态: pending...

  • 手写Promise

    今天来玩一下Promise,一步步分析。 原版Promise效果 自定义一个Pomise 执行结果执行结果 此时看...

  • 手写promise之分步解析

    promise是es6推出适用于异步请求的构造函数,帮助解决回调地狱的问题,以下内容将自定义实现promise,只...

  • 自定义Promise

    Promise是什么 Promise是异步编程的一种解决方案。具体表达:语法上来说,Promise是一个构造函数功...

  • 自定义promise

    promise的详细介绍[https://blog.csdn.net/weixin_44972008/articl...

  • JavaScript 自定义 Promise

    使用 Promise源代码 参考文章: Promise的封装

网友评论

      本文标题:自定义Promise

      本文链接:https://www.haomeiwen.com/subject/ycfgiktx.html