Javascript同步和异步进程优先级

Javascript同步和异步进程优先级,javascript,asynchronous,process,Javascript,Asynchronous,Process,我一直在研究javascript的异步行为,尽管它是单线程的,我在一条评论后说,对于这段代码: request(..., function (error, response, body) console.log('foo); }); callAComputationallyIntensiveSynchronousFunctionThatTakesSixHoursToExecute(); console.log('bar'); “bar”仍然位于“foo”之前

我一直在研究javascript的异步行为,尽管它是单线程的,我在一条评论后说,对于这段代码:

request(..., function (error, response, body)  
    console.log('foo);  
});  
    callAComputationallyIntensiveSynchronousFunctionThatTakesSixHoursToExecute();  
console.log('bar');  
“bar”仍然位于“foo”之前,因为Javascript总是首先完成当前正在执行的函数。事件永远不会中断函数

我知道同步函数执行比事件具有更高的优先级,但我不明白为什么在“foo”之前会打印“bar”。根据我的理解,应该进行异步调用,然后在响应准备就绪之前填充死区时间,它继续处理其他代码行,直到准备就绪,然后它应该为响应执行回调函数,然后返回处理代码,依此类推


然而,上面的示例说明,即使响应在同步函数执行结束之前很久就准备好了,它仍然会继续执行下一行代码。为什么会这样?

在JavaScript中,一切都是函数。同步函数和异步函数之间没有区别。 唯一的区别是调用这些函数的方式。所以“sync”/“async”对于程序员来说是一个抽象的概念,这使得通信更加容易

JavaScript的实际工作原理:

JavaScript有一个等待执行的“函数”队列。每次创建新的“异步函数”时,都会将其添加到此队列中。例如,当您执行
setTimeout()
、ajax调用或浏览器触发的“onClick”之类的DOM事件时,就会发生这种情况

如果一个特定的函数在JS中执行,它将永远不会被中断——它将一直运行,直到它完成(返回)。只有在之后,运行时(浏览器)才会查看队列,决定下一步应该执行哪个函数,然后调用它——等待它完成

在上面的示例中,浏览器当前正在执行打印“bar”的功能。此执行在完成之前不能中断,因此首先打印“条”。但是,在执行过程中,会创建一个新的异步函数并将其推送到执行队列。只有在打印了“bar”之后,运行时才会查看队列,找到“foo”函数并执行它

这样做的一个负面影响是长期运行的任务。执行此功能时,浏览器无法执行任何其他操作。甚至不呈现/更新页面。因此,如果您有一段运行时间为(比如)10秒的代码,则在功能完成之前,用户无法与网站进行交互。原因是,所有用户事件(如鼠标移动、单击和滚动事件)都已排队,在线程完成长时间运行的任务之前无法处理

使用JavaScript进行多线程处理


有了HTML5,JavaScript现在有机会使用多线程。但这是一个完全不同的话题,超出了这个问题的范围。请记住这在理论上是可能的。

谢谢您的回答,但我认为您可能误解了代码中的某些内容,但我不确定。console.log('bar')遵循计算权重函数,而不是函数的效果。从您所说的,我理解在完成“synchronous”函数之后,它应该查看队列,并查看请求是否正在等待执行,因为解析器没有到达console.log('bar')指令以将其添加到队列中。此外,运行时如何决定下一步选择队列中的哪个函数。例如,ajax调用实际上是异步的,它在自己的线程中运行。同时,浏览器继续原始脚本,最后将控件移动到用户(和事件队列)。当ajax线程准备就绪时,执行JS回调,这将为浏览器保留“唯一”线程。在与一些同事进一步讨论了这个答案之后,我想我现在完全理解了它的工作原理。脚本阻碍了函数的运行,它们是第一个添加到队列中的函数,然后它开始执行并向队列中添加新的“异步”函数,同时继续执行剩余的函数。只有在机器完成当前队列函数的执行后,在本例中是脚本本身,它才会查看队列并决定下一步执行哪个函数(可能是请求回调或其他脚本),而不是像我所想的那样在每次函数调用后执行。@Andu是的,它遵循计算量大的函数。所以只有6小时后才能打印。在这6个小时内,“foo”函数在队列中等待,并在“bar”打印完毕后启动。@Teemu正确,HTTP请求是浏览器在后台实际并行执行的少数事情之一。但这是一个浏览器细节——从JavaScript的角度来看,Ajax调用的响应是通过在主UI线程上运行的普通回调函数接收的——因此,如果当前正在进行6小时的作业,则不会执行该调用。