IT修真院-前端我爱编程

Js的同步异步以及回调函数

2018-01-27  本文已影响44人  风流司郎中

1.背景介绍

什么是同步,什么是异步?

2.知识剖析

javascript实现异步的原理

首先js是单线程的语言,即同一时间只能做做一件事。那Js如何实现异步的,异步和单线程不是自相矛盾吗?其实,单线程和异步确实不能同时成为一个语言的特性。js选择了成为单线程的语言,所以它本身不可能是异步的,但js的宿主环境(比如浏览器,Node)是多线程的,宿主环境通过某种方式(事件驱动,下文会讲)使得js具备了异步的属性

浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现三个常驻线程:javascript引擎线程,UI渲染线程,浏览器事件触发线程。
  1. javascript引擎线程是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序。

  2. UI渲染线程负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。但需要注意UI渲染线程与JS引擎是互斥的,当JS引擎执行时UI线程会被挂起,UI更新会被保存在一个队列中等到JS引擎空闲时立即被执行.

  3. 事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。


    image

UI线程和JS线程互斥的实例

<input type="text" value="" name="input" onkeydown="console.log(this.value)">
<input type="text" value="" name="input" onkeydown="var me=this;setTimeout(function(){console.log(me.value)},0)">

分析:第一个在keydown的时候,弹出来的是input里原来的value,而第2个在keydown的时候,却能弹出更新后的value,就是因为setTimeout,虽然他的delay设置为0,几乎是即时触发,但还是被添加到了执行队列后面,但就是这个过程,渲染已经完成了,当他回调函数执行时,输出来的已经是更新后的value了。

注意:js的工作机制是当线程空闲的情况下才会执行异步代码的回调函数
即当所有同步任务执行完毕后才会执行异步任务的回调函数

总结:当Js执行到异步任务后,会将异步任务交给浏览器进行执行,当执行有结果时会把异步任务的回调函数插入待处理队列的队尾。


3.常见问题

  1. ajax发送异步请求浏览器做了什么
  2. 有哪些常见异步回调函数?

4.解决方案

  1. ajax发送异步请求浏览器做了什么?
  1. 有哪些常见的异步回调函数?
  1. 浏览器处理点击事件的过程
<!doctype html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<div onclick="clickme()">click me</div>
<script type="text/javascript">
    function clickme() {
        console.log('点击事件')
    }
    for (i=0;i<50000;i++){
        console.log(i)
    }
</script>
</body>
</html>

在线实例
这个点击事件会等到for循环执行完毕后才会执行,即我们点击模块它直到for循环执行完毕才会执行


5.编码实战


6.扩展思考

如何实现js的多线程操作?

7.更多讨论


8.参考文献

参考一:js的单线程和异步
参考二:深入理解javascript异步编程障眼法&&h5 web worker实现多线程
参考三:谈谈JavaScript的异步实现- 小方- 博客园


PPT
视频

上一篇下一篇

猜你喜欢

热点阅读