2017-09-05 42 views
3

尽管我是研究关于JavaScript的异步行为被单线程和我的注释说明后传来,此代码:的Javascript同步和异步流程优先

request(..., function (error, response, body) 
    console.log('foo); 
}); 
    callAComputationallyIntensiveSynchronousFunctionThatTakesSixHoursToExecute(); 
console.log('bar'); 

“酒吧”依然会前“ foo',因为Javascript总是先完成当前正在执行的函数。事件永远不会中断函数。

我知道一个同步函数执行比事件具有更高的优先级,但我不明白为什么'bar'会在'foo'之前打印。从我的阅读中,应该进行异步调用,然后在响应准备好之前填充死区时间,然后继续并处理其他代码行直到准备就绪,然后应执行响应的回调函数之后返回到处理代码等等。

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

回答

1

在JavaScript中,一切都是功能。同步和异步功能之间没有区别。 唯一的区别就是你调用这些函数的方式。所以“同步”/“异步”是程序员的一个抽象概念,使得它更容易沟通。

如何JavaScript的实际工作:

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

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

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

这种负面影响是长期运行的任务。在执行这样的功能时,浏览器不能做其他事情。甚至没有渲染/更新页面。因此,如果您有一段运行时间为10秒的代码,则用户无法与网站进行交互,直到该功能完成。原因在于所有用户事件(如鼠标移动,点击和滚动事件)都排队等待,直到线程完成长时间运行的任务后才能处理。

多线程JavaScript的

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

+0

感谢您的回答,但我认为您可能会误解代码中的某些内容,但我不确定。'console.log('bar')'遵循computationalHeavyFunction,它不是函数的作用。根据你的说法,我明白在完成'同步'功能后,应该看看队列,看看请求正在等待执行,因为解析器没有到达console.log('bar' )指令将其添加到队列中。此外,运行时如何决定队列中的哪个函数选择下一个? – Andu

+0

不完全。例如,_ajax call_实际上是异步的,它在它自己的线程中运行。与此同时,浏览器继续原始脚本,并最终将控件移动到用户(和事件队列)。当ajax线程准备就绪时,会执行JS回调函数,它为浏览器保留“唯一”线程。 – Teemu

+0

在与一些同事讨论这个问题之后,我想我已经完全理解了这是如何工作的。脚本是它们的函数,它们是第一个被添加到队列中的,然后它开始执行并向队列中添加新的“异步”函数,同时继续执行剩余的函数。只有当机器完成执行当前队列功能(在本例中为脚本本身)之后,它才会按照我的假设查看队列并决定下一个要执行的功能(可能是请求回调或其他脚本),而不是在每个函数调用之后执行。 – Andu