JS回调函数相关

74 阅读3分钟
  • 回调函数 本质上就是一个普通函数
    • 一个函数A以实参的形式传递到 函数B中,在函数B中, 以形参的方式调用函数A,此时 函数A就可以称为 函数B 的回调函数
    • 回调函数的使用场景为异步代码的解决方案
        function A() {
            console.log('我是函数A')
        }

        function B(callback) {
            callback()
        }

        B(A)

        //基础版
        function fn(callback = () => { }) {
            console.log('班长, 帮我买瓶水')
            setTimeout(() => {
                console.log('班长, 买到水了')
                callback()
            }, 3000)
        }
        function jinnang() {
            console.log('在帮买一箱水')
        }
        fn(jinnang
        // 网络请求模拟
        function fn(chenggong, shibai) {
            const timer = Math.ceil(Math.random() * 3000)
            console.log('班长, 去帮我买瓶水')

            setTimeout(() => {
                if (timer > 2500) {
                    console.log('买水失败, 用时: ', timer)
                    shibai()
                } else {
                    console.log('买水成功, 用时: ', timer)
                    chenggong()
                }
            }, timer)
        }

        fn(
            () => { console.log('谢谢班长, 我和你开玩笑的, 退了吧!') },
            () => { console.log('买不到就别回来了') }
        )

回调地狱

这不是我们写代码的时候出现的某个漏洞,只是我们在利用回调函数解决问题的时候, 代码量多了之后的一个视觉体验

回调地狱的代码不利于我们去维护或者管理, 所以后续再处理异步任务的时候

我们需要一些更加简洁的方法,此时出现了一个东西 叫做 promise 他也是一个异步代码的解决方案

        // 调用 fn 函数 班长就回去 买水
        function fn(chenggong, shibai) {
            const timer = Math.ceil(Math.random() * 3000)
            console.log('班长, 去帮我买瓶水')

            setTimeout(() => {
                if (timer > 2900) {
                    console.log('买水失败, 用时: ', timer)
                    shibai()
                } else {
                    console.log('买水成功, 用时: ', timer)
                    chenggong()
                }
            }, timer)
        }

        /**
         *  需求: 
         *      在班长买水失败后, 让他再次去买水(重新调用 fn 函数)
         * 
         *  新需求: 如果班长 第二次也失败了, 让他继续去买水
         * 
         *  新需求: 第一次买水成功的时候, 让班长再去买一箱饮料
        */
        fn(
            () => {
                fn(
                    () => { console.log('班长买完水后, 又买了一箱饮料') },
                    () => { console.log('班长就买了一瓶水, 他不愿意给你们买饮料') }
                )
            },
            () => {
                fn(
                    () => { console.log('班长第二次买水 成功了') },
                    () => {
                        fn(
                            () => { console.log('班长第三次买水 成功了') },
                            () => { console.log('班长第三次买水 又失败了, 确实不争气') }
                        )
                    }
                )
            }
        )

promise

  • 作用: 一种新的异步代码封装方案, 用来代替 回调函数的
  • promise 的三个状态
    • 持续: pending
    • 成功: fulfilled
    • 失败: rejected

promise 只会在持续状态转换为 成功,或者 从持续状态转换为 失败 promise 的基本语法: promise 是 JS 内置的一个构造函数

    const p = new Promise()
  • new Promise 得到的对象 我们叫做 promise 对象, promise 对象上 有一些方法
    • then 方法 (会在 promise 状态成功的时候 执行)
    • catch 方法 (会在 promise 状态失败的时候 执行)
        const p = new Promise(function (resolve, reject) {
            /**
             *  形参名无所谓
             *      第一个形参: 内部的值是一个函数, 调用之后可以将当前这个 promise 的状态设置为 成功
             *      第二个形参: 内部的值是一个函数, 调用之后可以将当前这个 promise 的状态设置为 失败
            */

            // 书写我们的异步代码
            const timer = Math.ceil(Math.random() * 3000)
            console.log('班长, 去帮我买瓶水')

            setTimeout(() => {
                if (timer > 1500) {
                    console.log('买水失败, 用时: ', timer)
                    // shibai()
                    reject()
                } else {
                    console.log('买水成功, 用时: ', timer)
                    // chenggong()
                    resolve()
                }
            }, timer)
        })

        // console.log('打印 变量 p: ', p)

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