专栏首页web前端教室《JS回调是怎么回事》 | 7月28日微课 文字版

《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),作者:老尚

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 写不写js不重要,重要的是要有“分析问题”的思考方式

    今天早上在开始讲零基础课的时候,我看了一眼旁边桌上的书,就跟我的学生们聊了一会,看书的必要性。有些前端和互联网方面的书,确实是垃圾,但也要看看,为啥呢?因为面试...

    web前端教室
  • 大周末的不多说,面试十点必看

    实事求是的讲,前端新人因为时间的关系,对于JavaScript的理解确实是无法面面具到,甚至有些知识点我讲的比较深入,但因为每个人的程度不同,依然无法做到当堂理...

    web前端教室
  • 怎么做,前端开发才能从0到1...再到100?

    前端开发状态为0,就是什么都没有,一切都是空白。极端点甚至连javascript是啥都不知道。只知道这二年前端开发很火,就跑来学前端。想培训个三个月半年的,出来...

    web前端教室
  • 36 个JS 面试题为你助力金九银十(面试必读)

    在现代js中,let&const是创建变量的不同方式。 在早期的js中,咱们使用var关键字来创建变量。 let&const关键字是在ES6版本中引入的,其目的...

    Javanx
  • 36 个JS 面试题为你助力金九银十(面试必读)

    在现代js中,let&const是创建变量的不同方式。 在早期的js中,咱们使用var关键字来创建变量。 let&const关键字是在ES6版本中引入的,其目的...

    前端小智@大迁世界
  • 微软超融合私有云测试21-SCOM2016部署之安装SCOM管理服务器

    在上一篇文章中,我们将SCOM2016管理服务器所需的必备组件与SQL Server数据库已经安装完毕,下面我们开始正式安装SCOM管理服务器。

    SuperDream
  • 安装linux系统

    第1步:启动RHEL7的主机电源。 ? 第2步:敲击回车。 ? 第3步:等待即可。 ? 第4步:选择安装系统时的语言。 ? 第5步:配置信息界面,敲击“In...

    零月
  • 简单修复MacOS High Sierra 允许 Root 用户无密码登录的安全 Bug

    版权声明:本文为[他叫自己Mr.张]的原创文章,转载请...

    他叫自己MR.张
  • (一)主线程与工作线程的分工

    服务器端为了能流畅处理多个客户端链接,一般在某个线程A里面accept新的客户端连接并生成新连接的socket fd,然后将这些新连接的socketfd给另外开...

    范蠡
  • 死磕Java并发:J.U.C之读写锁:ReentrantReadWriteLock

    重入锁ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,但是在大多数场景下,大部分时间都是提供读服务,而写服务占有的时间较少。然而读...

    程序猿DD

扫码关注云+社区

领取腾讯云代金券