JavaScript异步之回调

版权声明:刘家军 https://blog.csdn.net/qq_42911663/article/details/85704283

回调函数

JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数,而这个过程就叫做回调

举一个常用的例子:约会结束了,你送女朋友回家,你说:“到家了别忘了给我发条信息。”然后女朋友回家以后给你发了条信息。其实这就是一个回调的过程。你留了个参数函数(让女朋友给你发条信息)给女朋友,然后女朋友回家,回家的动作是主函数。她必须先回到家以后,主函数执行完了,再执行传进去的函数,然后你就收到一条信息了。

通过例子我们可以基本了解了 然后继续上代码:

//定义主函数,回调函数作为参数
function A(callback) {
    callback && typeof callback == "function" && callback();
    console.log('我是主函数');      
}
//定义回调函数
function B(){
    setTimeout("console.log('我是回调函数')", 1000);//模仿耗时操作  
}
//调用主函数,将函数B传进去
A(B);

输出:
在这里插入图片描述

运用回调函数解决哪些问题

let name = "姓名"
function yh() {
name = "袁姮",
console.log(`我是${name}`)
}
function ljj() {
console.log(`这周末刘家军又约${name}了`)
}
yh()
ljj()

输出:
在这里插入图片描述
上面的代码输出是没什么问题的,不存在异步,都单线程同步执行,继续看代码:

let name = "姓名"
function yh() {
setTimeout(() =>{
name = "袁姮",
console.log(`我是${name}`)
},0)
}

function ljj() {
console.log(`这周末刘家军又约${name}了`)
}
yh()
ljj()

输出:
在这里插入图片描述
虽然定时器是0ms,但是yh函数确存在异步了,只有等主线程的内容走完,才能走异步函数
所以最简单的办法就是使用回调函数解决这种问题,ljj函数依赖于yh函数的执行结果,所以我们把ljj作为yh的一个回调函数

let name = "姓名"
function yh(callback) {
setTimeout(() =>{
name = "袁姮",
console.log(`我是${name}`)
callback && typeof callback == "function" && callback()
},0)
}

function ljj() {
console.log(`这周末刘家军又约${name}了`)
}
yh(ljj)

输出:
在这里插入图片描述
这个例子很简单,我继续往下讲
当回调的层级太多了,就会形成所说的“回调地狱,代码维护成本会高很多
我们看下面这个例子

     function funA(callBack) {
        console.log("A");
        setTimeout(() => {
          callBack()
        }, 100);
      }

      function funB() {
        console.log("B");
      }

      function funC(callBack) {
        console.log("C");
        setTimeout(() => {
          callBack()
        }, 1000);
      }

      function funD() {
        console.log("D");
      }

      function funE() {
        console.log("E");
      }

      function funF() {
        console.log("F");
      }

      funA(() => {
        funB()
        funC(() => {
          funD()
        })
        funE()
      })
      funF()

输出:
在这里插入图片描述
一般情况下,不会嵌套这么多层级,如果过多都会考虑拆分出来,此例子纯属用来练习;
如果你能看出输出顺序,那么对于回调函数也基本掌握,这段代码就不多做解释了,如果还是不怎么了解,那么debug一下看一下执行顺序,多看几遍再结合我前面所讲差不多就能理解了

链式回调

大家还是否记得在使用jQuery时,我们会经常这样去操作一个jQuery节点

$("element").show().css("color","red");

这也是利用链式调用,原理很简单:就是jQuery节点在调用api后都会返回节点自身,类似于:

let obj = {
   a: 0,
   fun(){
   this.a += 1
   return this
}
}
obj.fun().fun()
console.log(obj.a) // 2

现在大致理解了链式调用的原理了吧!
对于链式回调我们也经常接触,例如一些的各种确认框
下面举一个饿了么里面confirm弹框的例子this.$confirm().then().catch()

<template>
  <el-button type="text" @click="open">点击打开 Message Box</el-button>
</template>

<script>
  export default {
    methods: {
      open() {
        this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
        // 成功回调
          this.$message({
            type: 'success',
            message: '删除成功!'
          });
        }).catch(() => {
        // 失败回调
          this.$message({
            type: 'info',
            message: '已取消删除'
          });          
        });
      }
    }
  }
</script>

我相信很多人都会通过这种链式回调的方式处理异步回调(如ajax,可以看下我昨天的那个demo),因为可读性比普通的回调嵌套要高的多,但是维护的成本也要高出很多,而且实际开发中的情况要比这个复杂

今天就说到这里,预知后事如何,且听下次分解

猜你喜欢

转载自blog.csdn.net/qq_42911663/article/details/85704283
今日推荐