《JS回调是怎么回事》 | 7月28日微课 文字版

大家好,今晚的微课主要讲一个JS的回调。

这段时间51题练习群里有同学问回调是怎么回事?这个问题我竟然一时无法回答,因为简单的说就一句话,当事件完成,或条件达成,或请求返回的时候执行的代码段,就应该算是回调了。当然这是我自己的理解。

回调相对比较适当的说明是这样:

1, 回调函数可以做为参数,用匿名函数的形式传递给另一个函数;

2, 当某个函数运行到某种状态时,符合相应条件时,触发的函数,就是回调函数。

基本上这这二种定义,已经可以涵盖大多数情况了。关于回调函数的详细定义,我们不做过多说明,大家理解就好。

那为什么要用回调呢?

1, JS本身是单线程的,就是同时只有一个JS的线程,只有一段JS在执行。如果某个事务在运行时的时间很长,那我们不能让整个程序阻塞停下来等它完成。这时就需要用到异步操作。

那为什么JS要异步呢,因为JS从诞生之初就是运行在浏览器中,浏览器是一种GUI图形操作的场景。你点这,动那,拖动什么东西,你看这些都是事件处理。从交互角度来讲你不能对同一个元素进行二种操作,否则会产生交互阻塞了。假如JS二个线程,A线程向上移动某元素,B线程向下移动某元素,听谁的?

所以有了异步

典型的应用就是AJAX,它是非阻塞的。就是说,AJAX的语句不会让其余的JS语句停下来等它请求完成之后再继续执行。当一个AJAX请求发出去之后,后端接口什么时候会返回数据,其实是不知道的。这时JS就继续执行接下来的业务逻辑。然后当有数据从后端接口返回的时候,你之前预先在写好的处理返回数据的JS代码就可以自动发挥作用了。而在这期间,你并不必关心AJAX那一个部分的具体情况。

2, 一些我们自己封闭定义的工具函数,可以根据你传入的参数,来决定如何返回给你结果给你。

例如这样:

这就是一个回调的小demob了,在这个例子中JS运行的起点,

是第18行,toBack,它接收二个参数,分别一个config对象,和一个匿名函数,这个匿名函数做为toBack的第二个参数传入方法体。

传入toBack之后它的形参是callback,那么在ajax的success方法中,先进行了一个开关判断,然后把请求成功之后返回的data,做为参数,传入callback,也就是传回了当初传入toBack函数的第二个实参,也就是那个匿名函数中。

这时,再在匿名函数中调用了另一个函数tpl,将data传入其中。此时tpl相对于此匿名函数来讲,又是一个回调函数了。就这样,可以根据业务逻辑,以回调的方式一路写下去,可以写很长很长。再这其中要注册保持状态啊,结构啊,组件通信啊,这里就不展开了

而这个tpl从名字来讲,很明显是一个生成html的模板方法。而它又是由返回的数据来驱动调用的。这就是数据驱动视图。当然这又是另外一个话题了,这里不展开。

这样写的好处是很明显的,

1, 封装性很好,

2, 结构上比较紧凑,

3, 尽量减少暴露在外的全局变量,

4, 可扩展性好些,还可以继续再加变量或下一步的回调。

下面来说下,回调的时机,就是JS什么时候决定调用回调函数?

这还要从JS的单线程说起,单线程就意味着队列、阻塞。但有些业务什么时候完成,不知道。例如AJAX请求。这时可以把AJAX请求放在一边,先干手头的活。

这就意味着,JS所有的任务分二种,一种同步,另一种异步。同步就是排队;异步就是没准点的活儿先放任务队列里,什么时候它通知主线程说我这边完事了,什么时候再把它从任务队列里拿到主线程。

简单的来讲,它的运行机制是这样的,

1, 所有同步任务都在主线程上,即主栈;

2, 主栈之外,还有一个任务队列,也有叫消息队列的。只要异步任务结束,就将之添加入任务队列等待执行;

3, 一但主栈里的事件都执行完了,JS就读取任务队列。这时里面的那些已经结束的异步任务,就进入主线程,开始执行。

4, 不断重复上述1,2,3步骤。

然后异步事件并不只有AJAX,还有鼠标点击某处的事件,页面滚动到哪里时的事件等等,你肯定会在这些事件里写一些JS函数了,这些函数就是回调函数。当它们被触发的时候,这些函数就会进入任务队列,等待主线程执行。

一般意义上来讲,当主线程里的任务执行完了,就开始执行回调事件了。

当然了,这里还有一个问题,就是setTImeout定时器。主线程在检视任务线程的时候,会先查一下执行时间,如果你没到时候,是不会执行的。

还有一点要分清楚,就是JS本身是单线程的,但浏览器是多线程的。例如什么渲染DOM树线程的什么渲染线程啊,那其实都是浏览器干的。要真正的搞清楚这个东西,还要深入研究清楚浏览器的内部机制了。

好了,今天内容基本就这些了,JS就是这样,本身是一个很简单的脚本语言,很多地方,即使你不去深究,依然可以写的很好。但你要去深究,就会发现它内部的实现机制也很复杂,牵扯的点也很多。而更多的时候,这些内部实现的机制,你花费很大精力就去了解学习了,但你会发现相当时间内也不会对你有什么明显的提高,就是说你看了也白看,这是怎么回事呢?

因为JS内部机制看了之后,必须要靠代码量去加深理解。

而回调个话题就不再继续深入了。毕竟它是一个相对简单的技术点,大家先明白怎么用,为什么也就可以了。有兴趣的同学可以自己在网上查阅相关资料,有什么不懂的地方,可以留言给我。我有时间就会回复。

谢谢大家

原文发布于微信公众号 - web前端教室(webfeel)

原文发表时间:2016-07-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

《数据库系统概念》12-文件的组织

一个数据库被映射到多个不同的文件,这些文件由底层的操作系统来维护。每个文件分成定长的存储单元,称为块(bolck),块是存储分配和数据传输的基本单元。数据库默认...

2739
来自专栏北京马哥教育

Python 函数库 APIs 编写指南

2854
来自专栏我就是马云飞

设计模式二十四章经之状态模式

931
来自专栏前端那些事

Express4.x API (二):Request (译)

最近学习express想要系统的过一遍API,www.expressjs.com是express英文官网(进入www.epxressjs.com.cn发现也是只...

21011
来自专栏老马说编程

(67) 线程的基本协作机制 (上) / 计算机程序的思维逻辑

上节介绍了多线程之间竞争访问同一个资源的问题及解决方案synchronized,我们提到,多线程之间除了竞争,还经常需要相互协作,本节就来介绍Java中多线程协...

2096
来自专栏我和PYTHON有个约会

20. 企业级开发基础1:自定义模块

之前的课程中,我们已经了解了python程序设计开发的基础部分内容 包含了数据类型、变量、运算符、程序选择结构、循环结构、函数处理、字符串处理等等内容。 本...

823
来自专栏用户2442861的专栏

网易面试杂谈

http://blog.csdn.net/silangquan/article/details/18013967

692
来自专栏Java 技术分享

Struts2 配置文件小结

31410
来自专栏沈唁志

如何优化PHP性能呢?PHP性能优化总结

2233
来自专栏开发技术

spring-boot-2.0.3不一样系列之源码篇 - SpringApplication的run方法(一)之SpringApplicationRunListener,绝对有值得你看的地方

  Springboot启动源码系列还只写了一篇,已经过去一周,又到了每周一更的时间了(是不是很熟悉?),大家有没有很期待了?我会尽量保证启动源码系列每周一更,...

1502

扫码关注云+社区