Tar*_*yan 26 javascript browser v8 spidermonkey chakra
我处在一个尴尬的境地,
我使用纯JavaScript已经有近3年了,我知道JavaScript是单线程语言,你可以使用setInterval
和setTimeout
函数来模拟异步执行,
但当我想到他们如何工作时,我无法清楚地理解它.那么这些函数如何影响执行上下文?
我想在特定时间内只运行代码的一部分,然后切换到另一部分.如果是这样,那么很多setInterval
或者setTimeout
电话会影响性能吗?
CDT*_*CDT 24
Javascript是单线程的,但浏览器不是.浏览器至少有三个主题:Javascript引擎线程,UI线程和定时线程,其中的时间setTimeout
和setInterval
由定时线程中完成的.
当调用setTimeout
or时setInterval
,浏览器中的计时器线程开始倒计时,并且当时间到时将回调函数放入javascript线程的执行堆栈中.在堆栈中的其他函数完成之前,不执行回调函数.因此,如果在时间到时执行其他耗时的函数,则回调setTimeout
将无法及时完成.
浏览器具有用于计时器功能的API,就像用于事件ex的API一样。
“点击”
'滚动'
假设您的应用程序中包含以下代码
function listener(){
...
}
setTimeout(listener, 300)
function foo(){
for(var i = 0; i < 10000; i++){
console.log(i)
}
}
foo()
Run Code Online (Sandbox Code Playgroud)
此时,根据我们在调用堆栈上方编写的代码,
调用堆栈-> foo
并假设foo将花费1s来完成其执行,因为我们已经在代码中定义了1个超时,并且我们在“ foo”完成之前即在300ms之前运行它
那会发生什么呢?
javascript是否会停止执行foo并开始执行setTimeout?
没有
我们已经知道javascript是单线程的,因此它必须先完成foo的执行,然后浏览器才能确保在执行foo之后“ setTimeout”将执行?
这里的JavaScript魔术变成了图片
300ms到期后,浏览器“ Timer API”启动,并将超时处理程序放入“ Message Queue”
此时,上图中的“消息队列”看起来像
消息队列-> setTimout:listner
和
调用堆栈-> foo
当“调用堆栈”为空(即foo完成)时,如图所示,“事件循环”将从消息队列中获取消息并将其推入堆栈
“事件循环”的唯一工作是当“调用堆栈”为空并且其中有“消息队列”条目时,然后使消息形式“消息队列”出队,并将其推入“调用堆栈”
此时,上图中的Message Queue看起来像
消息队列->
和
调用堆栈->监听器
这就是setTimeout和setInterval的工作方式,即使我们在setTimeout中指定300 ms,在这种情况下,它将在“ foo”完成执行后(即1s之后)执行。这就是为什么在setTimeout / setInterval中指定的计时器指示函数执行的“最小时间”延迟。
Javascript 是单线程的,但浏览器不是。
有 1 个堆栈用于执行函数和语句。有 1 个队列,函数在其中排队等待执行。有一些 Web API 可以在特定时间保存函数,在事件表中的 setTimeout 和 setInterval 中定义。
当 javascript 引擎逐行执行 js 文件时,如果它找到一行作为语句或函数调用,则将其加载到堆栈上并执行,但如果是 setTimeout 或 setInterval 调用,则与 setTimeout 或 setInterval 关联的函数处理程序被 TIME API 取出(浏览器的 Web API 之一)并保留它。
一旦这个时间结束,Time Api 将该函数放在执行队列的末尾。
现在该函数的执行取决于队列中前面的其他函数调用。
注意:此函数调用是在 window 对象上调用的。
setTimeout(function () {console.log(this)}, 300)
窗口{postMessage:ƒ,模糊:ƒ,焦点:ƒ,关闭:ƒ,框架:窗口,...}
归档时间: |
|
查看次数: |
17271 次 |
最近记录: |