- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
语法的哪一部分提供了该函数应该在其他线程中运行并且是非阻塞的信息?
让我们考虑 node.js 中的简单异步 I/O
var fs = require('fs');
var path = process.argv[2];
fs.readFile(path, 'utf8', function(err,data) {
var lines = data.split('\n');
console.log(lines.length-1);
});
究竟是什么让它发生在后台?任何人都可以准确地解释它或粘贴一些好的资源的链接吗?在我所见之处,到处都有关于什么是回调的大量信息,但没有人解释为什么它实际上是这样工作的。
这不是关于node.js的具体问题,而是关于每种编程语言中回调的一般概念。
编辑:
我提供的示例在这里可能不是最好的。所以我们不要考虑这个 node.js 代码片段。我一般问 - 是什么让程序在遇到回调函数时继续执行的技巧。语法是什么这使得回调概念成为非阻塞概念?
提前致谢!
最佳答案
语法中没有告诉你你的回调是异步执行的。回调可以是异步的,例如:
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);
Javascript 本身没有任何使函数异步的特性。如果你想写一个异步函数,你有两种选择:
使用另一个异步函数,例如 setTimeout
或网络 worker 来执行你的逻辑。
用 C 编写。
C语言函数(如setTimeout
)是如何实现异步执行的?这一切都与事件循环(或大部分)有关。
在网络浏览器中有一段用于联网的代码。最初,网络代码只能下载一件事:HTML 页面本身。当马赛克发明 <img>
标记网络代码演变为下载多个资源。然后网景实现了progressive rendering对于图像,他们必须使网络代码异步,以便他们可以在加载所有图像之前绘制页面并逐步和单独地更新每个图像。这就是事件循环的由来。
在浏览器的核心有一个从异步网络代码演变而来的事件循环。因此,它使用 I/O 原语作为其核心也就不足为奇了: select()
(或类似的东西,如 poll、epoll 等,取决于操作系统)。
select()
C 中的函数允许您在单个线程中等待多个 I/O 操作,而无需产生额外的线程。 select()
看起来像:
select (max, readlist, writelist, errlist, timeout)
要让它等待 I/O(来自套接字或磁盘),您需要将文件描述符添加到 readlist
当您的任何 I/O channel 上有可用数据时,它将返回。一旦它返回,您就可以继续处理数据。
javascript 解释器保存您的回调,然后调用 select()
功能。当select()
返回解释器确定哪个回调与哪个 I/O channel 相关联,然后调用它。
方便,select()
还允许您指定 timeout
值(value)。通过精心管理timeout
传递给 select()
您可以在将来的某个时间调用回调。这就是 setTimeout
和 setInterval
被实现。解释器保留所有超时的列表并计算它需要传递的内容为timeout
。至select()
.那么当select()
除了查明是否有任何由于 I/O 操作而需要调用的回调之外,解释器还会检查任何需要调用的过期超时。
所以 select()
仅此一项就涵盖了实现异步功能所需的几乎所有功能。但是现代浏览器也有网络 worker 。在 web worker 的情况下,浏览器会产生线程来异步执行 javascript 代码。要与主线程通信,worker 仍必须与事件循环(select()
函数)交互。
Node.js 在处理文件/磁盘 I/O 时也会产生线程。当 I/O 操作完成时,它会与主事件循环返回通信以执行相应的回调。
希望这能回答您的问题。我一直想写这个答案,但之前很忙。如果您想了解更多关于 C 中非阻塞 I/O 编程的信息,我建议您阅读以下内容:http://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html
有关更多信息,另请参阅:
关于javascript - 我知道回调函数是异步运行的,但是为什么呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29883525/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!