promise方法相关

42 阅读5分钟

1.将 promise 封装到函数中

        function fn() {
            const p = new Promise(function (resolve, reject) {
                const timer = Math.ceil(Math.random() * 3000)
                console.log('班长, 去帮我买瓶水')

                setTimeout(() => {
                    if (timer > 1500) {
                        console.log('买水失败, 用时: ', timer)
                        reject('买水失败是因为时间超过 1500 毫秒')
                    } else {
                        console.log('买水成功, 用时: ', timer)
                        resolve('买水成功是因为 时间小于 1500 毫秒')
                    }
                }, timer)
            })

            return p
        }

        // 得到 fn 函数内部的 promise 对象
        const res = fn()

        // 普通调用
         res.then(() => {
             console.log('如果我这行内容打印, 说明 promise 的状态为 成功')
         })
         res.catch(() => {
             console.log('如果我这行内容打印, 说明 promise 的状态为 失败')
         })

        // 链式调用
        res.then((str) => {
            console.log('如果我这行内容打印, 说明 promise 的状态为 成功', str)
        }).catch((str) => {
            console.log('如果我这行内容打印, 说明 promise 的状态为 失败', str)
        })

        function fn() {
            const p = new Promise(function (resolve, reject) {
                const timer = Math.ceil(Math.random() * 3000)
                console.log('班长, 去帮我买瓶水')

                setTimeout(() => {
                    if (timer > 1500) {
                        reject('超时, 所以买水失败')
                    } else {
                        resolve('没有超时, 买水成功')
                    }
                }, timer)
            })

            return p
        }

        // 得到 fn 函数内部的 promise 对象
        const res = fn()

        /**
         *  当你在第一个 then 里面 返回一个 新的 promise 对象
         * 
         *  然后你可以在 第一个 then 的后面 再次书写一个 then
        */

        // 链式调用
        res.then((str) => {
            console.log(`因为 ${str}, 所以奖励班长 10 个 bug`)

            return fn()
        }).then((str) => {
            console.log('如果我输出了, 表示班长 第二次买水成功')

            return fn()
        }).then((str) => {
            console.log('如果我输出了, 表示班长 第三次买水成功')

        }).catch((str) => {
            console.log(`如果我输出了, 说明之前某一次买水失败了`)
        })

2.async 与 await

是 promise 的一种调用方案 (也就是说 必须结合着 promise 一起使用)

能够将 异步代码, 写的像 "同步代码一样

  • async: 书写在 一个函数的 开头, 表明当前函数是一个异步函数, 内部可以书写 await
  • await: 具有等待的含义, 书写在 异步函数 前, 代码运行到这个位置的时候, 会有一个等待效果

一直等到这个异步任务结束, 并且将异步任务的反馈结果 当一个值返回出来

        function fn() {
            const p = new Promise(function (resolve, reject) {
                const timer = Math.ceil(Math.random() * 3000)
                console.log('班长, 去帮我买瓶水')

                setTimeout(() => {
                    if (timer > 5000) {
                        reject('超时, 所以买水失败')
                    } else {
                        resolve('没有超时, 买水成功')
                    }
                }, timer)
            })

            return p
        }

        newFn()
        async function newFn() {
            // 因为函数开头写了 async, 所以这个函数就是一个独特的异步函数, 内部可以书写 await

            // await 是等待的意思, 他必须等待后边的 promise 结束后再往下继续执行代码
            const r1 = await fn()
            console.log('第一次买水: ', r1)

            const r2 = await fn()
            console.log('第二次买水: ', r2)

            const r3 = await fn()
            console.log('第三次买水: ', r3)
        }

3.async 与 await 的缺点

不能正常的捕获到 promise 的失败状态

    1. try...catch
    1. 封装一个永远不会失败的 promise 也就是说 不管请求状态如何, 永远调用 resolve 让 promise 的状态一定是成功

为了区分这次请求是成功还是失败, 我们不在单纯的返回一个字符串了

而是返回一个对象

注意: 这个对象 我们约定 里边有一个 code 属性, 成功时赋值为 1, 失败时赋值为 0

        function fn() {
            const p = new Promise(function (resolve, reject) {
                const timer = Math.ceil(Math.random() * 3000)
                console.log('班长, 去帮我买瓶水')

                setTimeout(() => {
                    if (timer > 1500) {
                        // reject('超时, 所以买水失败')
                        resolve({
                            code: 0, // 代表当前请求失败
                            msg: '超时, 所以买水失败'
                        })
                    } else {
                        resolve({
                            code: 1,    // 代表当前请求成功
                            msg: '没有超时, 买水成功'
                        })
                    }
                }, timer)
            })

            return p
        }

        newFn()
        // 解决缺点 方案2
        async function newFn() {
            const r1 = await fn()
            if (r1.code === 0) {
                console.log('请求失败的补救措施')
            } else {
                console.log('请求成功, 正常执行代码即可')
            }
        }


        // newFn()
        // 解决缺点 方案1
         async function newFn() {
             try {
                 const r1 = await fn()
                 console.log('第一次买水: ', r1)
             } catch (error) {
                 console.log(error)
             }
             try {
                 const r1 = await fn()
                 console.log('第二次买水: ', r1)
             } catch (error) {
                 console.log(error)
             }
         }

4.promise 的其他方法

        function fn() {
            const p = new Promise(function (resolve, reject) {
                const timer = Math.ceil(Math.random() * 3000)
                console.log('班长, 去帮我买瓶水')
                setTimeout(() => {
                    if (timer > 1500) {
                        reject('超时, 所以买水失败')
                    } else {
                        resolve('没有超时, 买水成功')
                    }
                }, timer)
            })
            return p
        }

        // 1. promise 对象上的方法
        // const res = fn()
        // res.then(() => {
        //     console.log('成功时执行')
        // }).catch(() => {
        //     console.log('失败时执行')
        // }).finally(() => {
        //     /**
        //      *  正常业务场景中, 我们再发起一个请求的时候, 会将页面弹出一个遮罩层
        //      *  然后再请求结束的时候 需要将这个遮罩层关闭
        //      *  这个时候如果放在 then 中 那么会有一个 问题, 就是请求失败的时候不会触发then
        //      *  所以我们一般不会放在 then 关闭遮罩层, 而是 放在 finally 中
        //     */
        //     console.log('每一次都会执行 (不会考虑成功还是失败)')
        // })

        // 2. promise 构造函数上的一些方法
        // Promise.all([fn(), fn(), fn()]).then(() => {
        //     console.log('所有的 参数 全部都返回一个 成功状态的时候, 会执行')
        // }).catch(() => {
        //     console.log('所有参数中, 有一个为失败状态, 就会执行 catch')
        // })

        Promise.race([fn(), fn(), fn()]).then(() => {
            console.log('这些参数中, 结束最快的哪一个状态为 成功的时候执行')
        }).catch(() => {
            console.log('这些参数中, 结束最快的哪一个状态为 失败的时候执行')
        })

        function fn() {
            const p = new Promise(function (resolve, reject) {
                const timer = Math.ceil(Math.random() * 3000)
                console.log('班长, 去帮我买瓶水')
                setTimeout(() => {
                    if (timer > 1500) {
                        reject('超时, 所以买水失败')
                    } else {
                        resolve('没有超时, 买水成功')
                    }
                }, timer)
            })
            return p
        }

        // Promise.allSettled([fn(), fn(), fn()]).then((res) => {
        //     /**
        //      *  在数组内传递的 promise 全都执行完毕后, 返回一个数组给到 then 函数
        //      * 
        //      *  数组内的对象就是我们传递进来的 promise 对象的执行结果
        //     */
        //     console.log(res)
        // })

        Promise.resolve().then(() => {
            console.log('强制返回一个 状态为 成功的 promise')
        })

        Promise.reject().then(() => {
            console.log('如果我打印了, 说明 当前的 promise 状态为成功')
        }).catch(() => {
            console.log('强制返回一个 状态为 失败的 promise 对象')
        })