js中特殊的宏任务10bet

来源:http://www.chinese-glasses.com 作者:Web前端 人气:76 发布时间:2020-04-07
摘要:10bet,时间: 2019-10-11阅读: 82标签: 任务一.setImmediate setTimeout用法在实际项目中还是会时常遇到。比如浏览器会聪明的等到一个函数堆栈结束后才改变DOM,如果再这个函数堆栈中把页面背

10bet,时间: 2019-10-11阅读: 82标签: 任务一.setImmediate

setTimeout用法在实际项目中还是会时常遇到。比如浏览器会聪明的等到一个函数堆栈结束后才改变DOM,如果再这个函数堆栈中把页面背景先从白色设为红色,再设回白色,那么浏览器会认为DOM没有发生任何改变而忽略这两句话,因此我们可以通过setTimeout把“设回白色”函数加入下一个堆栈,那么就可以确保背景颜色发生过改变了(虽然速度很快可能无法被察觉)。

目前只有IE10+和NodeJS支持该API。

  总之,setTimeout增加了Javascript函数调用的灵活性,为函数执行顺序的调度提供极大便利。

立即触发回调函数,使其进入宏任务队列(macro task queue)

然后,我们从基础的层面来看看:理解JavaScript的定时器是如何工作的是非常重要的。

语法:

计时器的执行常常和我们的直观想象不同,那是因为JavaScript引擎是单线程的。我们先来认识一下下面三个函数是如何控制计时器的。

// 只有一个参数setImmediate(callback)

var id = setTimeout(fn, delay); - 初始化一个计时器,然后在指定的时间间隔后执行。该函数返回一个唯一的标志ID(Number类型),我们可以使用它来取消计时器。

比setTimout(fn, 0)的执行顺序要快,性能也更高。因为setTimeout(fn,0)实质上会有4ms的延迟。

var id = setInterval(fn, delay); - 和setTimeout有些类似,但它是连续调用一个函数(时间间隔是delay参数)直到它被取消。

二. MessageChannelAPI1. 作用

clearInterval(id);, clearTimeout(id); - 使用计时器ID(setTimeout 和 setInterval的返回值)来取消计时器回调的发生

MessageChannelAPI允许我们新建一个消息通道,并通过它的两个属性port1和port2进行通信。

 

实质是通过一个端口发送数据,另一个端口通过onmessage监听另一个端口发送的数据。

有一个基本的概念你得记住了:

触发方式:

时间延迟不能被保证。什么意思,就是说你这样写setTimeout(fn, 500)并不代表fn肯定在500毫秒之后马上就执行,延迟很可能会更长。因为 JavaScript 是单线程语言,所有的异步事件(包括计时器、鼠标事件或者一个 XMLHttpRequest 完成)仅仅当程序执行期间有缺口的时候才会执行,不是你规定了什么时候就什么时候执行,要知道程序员不是万能的,你写的东西最终还是要看浏览器脸色的。

同步触发,即port发送数据时立即触发。所以会比setTimeout(fn,0)触发要早。

 

  1. 使用

用一个很好的图表加以说明:

MessageChannel是个构造函数。使用前需要创建实例,生成一条消息通道。

 10bet 1

const channel = new MessageChannel();

 

实例自带两个端口,即消息通道的两端

JavaScript引擎用单线程运行也是有意义的,单线程不必理会线程同步这些复杂的问题,问题得到简化.

const port1 = channel.port1;const port2 = channel.port2;

那么单线程的JavaScript引擎是怎么配合浏览器内核处理这些定时器和响应浏览器事件的呢?
下面结合浏览器内核处理方式简单说明.

示例:(模拟setimmediate)

浏览器内核实现允许多个线程异步执行,这些线程在内核制控下相互配合以保持同步.假如某一浏览器内核的实现至少有三个常驻线 程:javascript引擎线程,界面渲染线程,浏览器事件触发线程,除些以外,也有一些执行完就终止的线程,如Http请求线程,这些异步线程都会产 生不同的异步事件,下面通过一个图来阐明单线程的JavaScript引擎与另外那些线程是怎样互动通信的.虽然每个浏览器内核实现细节不同,但这其中的 调用原理都是大同小异.

const channel = new MessageChannel();const port1 = channel.port1;const port2 = channel.port2;port1.onmessage = function(e) { console.log(e.data);}setTimeout(function() { console.log(‘settimeout‘); //4ms})port2.postMessage(‘hello world‘); //立即Promise.resolve().then(() = { console.log(‘then‘); // 微任务})// 运行结果then hello worldsettimeout

10bet 2

由图可看出,浏览器中的JavaScript引擎是基于事件驱动的,这里的事件可看作是浏览器派给它的各种任务,这些任务可以源自 JavaScript引擎当前执行的代码块,如调用setTimeout添加一个任务,也可来自浏览器内核的其它线程,如界面元素鼠标点击事件,定时触发 器时间到达通知,异步请求状态变更通知等.从代码角度看来任务实体就是各种回调函数,JavaScript引擎一直等待着任务队列中任务的到来.由于单线 程关系,这些任务得进行排队,一个接着一个被引擎处理.

 

 

IE8及其之前的IE版本更新间隔为15.6毫秒。假设你设定的setTimeout延迟为16.7ms,那么它要更新两个15.6毫秒才会该触发延时。这也意味着无故延迟了 15.6 x 2 - 16.7 = 14.5毫秒。

           16.7ms
DELAY: |------------|

CLOCK: |----------|----------|
         15.6ms    15.6ms

本文由10bet发布于Web前端,转载请注明出处:js中特殊的宏任务10bet

关键词:

最火资讯