我正在研究javascript的异步行为,尽管它是单线程的,我在发表评论后发现这条代码:
request(..., function (error, response, body)
console.log('foo);
});
callAComputationallyIntensiveSynchronousFunctionThatTakesSixHoursToExecute();
console.log('bar');
'bar'仍然会出现在'foo'之前,因为Javascript总是先完成当前正在执行的函数。事件永远不会中断函数。
我知道同步函数执行的优先级高于事件,但我不明白为什么'bar'会在'foo'之前打印出来。从我的阅读中,应该进行异步调用,然后在响应准备就绪之前填充死区时间,它继续处理其他代码行直到它准备就绪,然后它应该执行响应的回调函数然后返回处理代码等等。
上面的例子表明,即使响应在同步函数执行完毕之前就已经准备就绪,它仍会继续并执行下一行代码。那是为什么?
答案 0 :(得分:1)
在JavaScript中,一切都是功能。同步和异步功能之间没有区别。 唯一的区别是你调用这些函数的方式。因此,“sync”/“async”是程序员的一个抽象概念,它使通信更容易。
JavaScript实际运作方式:
JavaScript有一个等待执行的“函数”队列。每次创建新的“异步函数”时,都会将其添加到此队列中。例如,当您执行setTimeout()
,ajax调用或仅浏览器触发的“onClick”等DOM事件时,会发生这种情况。
如果在JS中执行特定的功能,它将永远不会被中断 - 它会一直运行直到完成(返回)。之后,运行时(浏览器)会查看队列,决定接下来应该执行哪个函数,然后调用它 - 等待它完成。
在上面的示例中,浏览器当前正在执行将打印“bar”的功能。此执行在完成之前不能中断,因此首先打印“bar”。但是,在执行期间,会创建一个新的异步函数并将其推送到执行队列。只有在打印完“bar”后,运行时才会查看队列,找到“foo”函数并执行它。
这种负面影响是长期运行的任务。执行此类功能时,浏览器无法执行任何其他操作。甚至不渲染/更新页面。因此,如果你有一段代码运行10秒钟,那么在功能完成之前,用户无法与网站进行交互。原因是所有用户事件,如鼠标移动,点击和滚动事件都排队等待,直到线程完成长时间运行的任务才能处理。
使用JavaScript进行多线程
使用HTML5,JavaScript现在有机会使用web workers使用多个线程。但这是一个完全不同的主题,超出了这个问题的范围。请记住,这在理论上是可行的。