有 没有 在告诉你,你的回调是异步执行的语法。回调可以是异步的,例如:
setTimeout(function(){ console.log("this is async");}, 100);或者可以是同步的,例如:
an_array.forEach(function(x){ console.log("this is sync");});因此,您如何知道某个函数将同步还是异步调用回调?唯一可靠的方法是阅读文档。
您还可以编写测试来确定文档是否不可用:
var t = "this is async";some_function(function(){ t = "this is sync";});console.log(t);异步代码如何工作
Java本身不具有使函数异步的任何功能。如果要编写异步函数,则有两个选择:
使用另一个异步函数(例如
setTimeout
或Web Worker)来执行您的逻辑。用C写
至于C编码函数(例如
setTimeout)如何实现异步执行?这一切都与事件循环(或大部分)有关。
事件循环
Web浏览器内部有这段代码用于网络连接。最初,网络代码只能下载一件事:HTML页面本身。当Mosaic发明
<img>标签时,网络代码演变为下载多种资源。然后,Netscape实施了图像的渐进式渲染,他们必须使联网代码异步,以便他们可以在加载所有图像之前绘制页面,并逐步和逐个更新每个图像。这是事件循环的起源。
在浏览器的中心,有一个从异步网络代码演变而来的事件循环。因此,它使用I /
O原语作为其核心就不足为奇了:
select()或类似OS之类的类似民意调查,epoll等)。
select()C语言中的函数使您可以在单个线程中等待多个I / O操作,而无需生成其他线程。
select()看起来像:
select (max, readlist, writelist, errlist, timeout)
要让它等待I / O(来自套接字或磁盘),您可以将文件描述符添加到中
readlist,当任何I /
O通道上有可用数据时,它将返回。一旦返回,您就可以继续处理数据。
javascript解释器保存您的回调,然后调用该
select()函数。当
select()返回时,解释器找出哪个回调与哪个I /
O通道关联,然后调用它。
方便地,
select()还允许您指定一个
timeout值。通过仔细管理
timeout传递给
select()您的内容,可以导致将来某个时候调用回调。这是怎么
setTimeout和
setInterval实现。解释器会保留所有超时的列表,并计算需要传递的
timeout时间
select()。然后,当
select()返回时,除了要确定是否由于I
/ O操作需要调用任何回调外,解释器还会检查是否需要调用任何过期的超时。
因此,
select()仅涉及实现异步功能所需的几乎所有功能。但是现代浏览器也有网络工作者。对于网络工作者,浏览器会生成线程以异步执行javascript代码。为了与主线程通信,工作人员必须仍然与事件循环(
select()函数)交互。
在处理文件/磁盘I / O时,Node.js也产生线程。I / O操作完成后,它将与主事件循环通信回去,以使适当的回调得以执行。



