JavaScript何时同步?
我一直认为JavaScript总是异步的。然而,我已经了解到,有些情况下它不是(即DOM操作)。关于什么时候是同步的,什么时候是异步的,有什么好的参考吗?jQuery会影响这一点吗?JavaScript是单线程的,并且您一直在处理正常的同步代码流执行 JavaScript可以具有异步行为的好例子是事件(用户交互、Ajax请求结果等)和计时器,基本上是随时可能发生的动作 我建议您查看以下文章:JavaScript何时同步?,javascript,jquery,Javascript,Jquery,我一直认为JavaScript总是异步的。然而,我已经了解到,有些情况下它不是(即DOM操作)。关于什么时候是同步的,什么时候是异步的,有什么好的参考吗?jQuery会影响这一点吗?JavaScript是单线程的,并且您一直在处理正常的同步代码流执行 JavaScript可以具有异步行为的好例子是事件(用户交互、Ajax请求结果等)和计时器,基本上是随时可能发生的动作 我建议您查看以下文章: 这篇文章将帮助您理解JavaScript的单线程特性,以及计时器如何在内部工作以及异步JavaSc
JavaScript始终是同步的和单线程的。如果在页面上执行JavaScript代码块,则当前不会执行该页面上的其他JavaScript JavaScript只是异步的,例如它可以进行Ajax调用。Ajax调用将停止执行,其他代码将能够执行,直到调用返回(成功或其他),此时回调将同步运行。此时将不会运行其他代码。它不会中断当前正在运行的任何其他代码 JavaScript计时器使用这种回调进行操作 将JavaScript描述为异步可能会产生误导。更准确地说,JavaScript是同步的、单线程的,具有各种回调机制
jQuery在Ajax调用上有一个同步选项(使用
async:false
选项)。初学者可能会错误地使用它,因为它允许一种更为传统的编程模型,人们可能更习惯于这种模型。出现问题的原因是此选项将阻止页面上的所有JavaScript,直到完成为止,包括所有事件处理程序和计时器。JavaScript是单线程的,具有同步执行模型。单线程意味着一次执行一个命令。同步是指一次执行一行代码,即一次执行一行代码,以便代码出现。所以在JavaScript中,一次只发生一件事
执行上下文
JavaScript引擎与浏览器中的其他引擎交互。
在JavaScript执行堆栈的底部有一个全局上下文,当我们调用函数时,JavaScript引擎会为各个函数创建新的执行上下文。当被调用函数退出时,其执行上下文将从堆栈中弹出,然后弹出下一个执行上下文,依此类推
比如说
function abc()
{
console.log('abc');
}
function xyz()
{
abc()
console.log('xyz');
}
var one = 1;
xyz();
在上面的代码中,将创建一个全局执行上下文,并在此上下文中存储var one
,其值将为1。。。调用xyz()调用时,将创建一个新的执行上下文,如果我们在xyz函数中定义了任何变量,这些变量将存储在xyz()的执行上下文中。在xyz函数中,我们调用abc(),然后创建abc()执行上下文并将其放在执行堆栈上。。。现在,当abc()完成时,它的上下文从堆栈中弹出,然后xyz()上下文从堆栈中弹出,然后全局上下文将弹出
现在谈谈异步回调;异步意味着一次不止一个
与执行堆栈一样,还有事件队列。当我们想要得到JavaScript引擎中某个事件的通知时,我们可以监听该事件,并且该事件被放置在队列中。例如,Ajax请求事件或HTTP请求事件
每当执行堆栈为空时,如上面的代码示例所示,JavaScript引擎会定期查看事件队列,并查看是否有任何要通知的事件。例如,队列中有两个事件,一个ajax请求和一个HTTP请求。它还查看是否有一个函数需要在该事件触发器上运行。。。因此JavaScript引擎会收到有关事件的通知,并知道要在该事件上执行的相应函数。。。因此JavaScript引擎调用处理程序函数,在本例中,将调用AjaxHandler(),与调用函数时一样,它的执行上下文放在执行上下文上,现在函数执行完成,事件ajax请求也从事件队列中删除。。。当AjaxHandler()完成时,执行堆栈为空,因此引擎再次查看事件队列并运行HTTP请求的事件处理程序函数,该函数是队列中的下一个。请务必记住,只有在执行堆栈为空时才处理事件队列
例如,请参阅下面的代码,解释Javascript引擎的执行堆栈和事件队列处理
function waitfunction() {
var a = 5000 + new Date().getTime();
while (new Date() < a){}
console.log('waitfunction() context will be popped after this line');
}
function clickHandler() {
console.log('click event handler...');
}
document.addEventListener('click', clickHandler);
waitfunction(); //a new context for this function is created and placed on the execution stack
console.log('global context will be popped after this line');
JavaScript引擎同步运行代码,如执行上下文部分所述,浏览器异步将内容放入事件队列。因此,需要很长时间才能完成的函数可能会中断事件处理。浏览器中发生的事件(如事件)由JavaScript以这种方式处理,如果有一个侦听器应该运行,那么引擎将在执行堆栈为空时运行它。事件按照发生的顺序进行处理,因此异步部分是关于引擎外部发生的事情,即当这些外部事件发生时,引擎应该做什么
所以JavaScript总是同步的。对于真正了解JS工作原理的人来说,这个问题似乎不太可能,但是大多数使用JS的人没有如此深刻的洞察力(也不一定需要它),对于他们来说,这是一个相当令人困惑的问题,我将尝试从这个角度回答。
<html>
<head>
</head>
<body>
<script src="program.js"></script>
</body>
</html>
waitfunction() context will be popped after this line
global context will be emptied after this line
click event handler...
let a = [1, 4, 15, 7, 2];
let sum = 0;
for (let i = 0; i < a.length; i++) {
sum += a[i];
}
Test start...
Test finish...
Finish!
A-Start ------------------------------------------ A-End
| B-Start -----------------------------------------|--- B-End
| | C-Start ------------------- C-End | |
| | | | | |
V V V V V V
1 thread->|<-A-|<--B---|<-C-|-A-|-C-|--A--|-B-|--C-->|---A---->|--B-->|