我看到这篇帖子:https://www.codementor.io/nodejs/tutorial/manage-async-nodejs-callback-example-code,运行代码后我确认nodejs是异步的。 但是我创建了2个js文件来再次测试nodejs的异步功能。
文件1: callback_example.js
exports.countless = function(callback){
var date = new Date();
console.log("*" + date.getSeconds());
var x = 0;
for(var i = 1; i <= 1000000000; i++){
x++;
}
callback(x);
date = new Date();
console.log("**" + date.getSeconds());
}
exports.check = function(callback){
var date = new Date();
console.log(date.getSeconds());
callback(123);
date = new Date();
console.log(date.getSeconds());
}
文件2: call.js
var call = require('./callback_example');
call.countless(function(x){
console.log(x);
});
call.check(function(x){
console.log(x);
});
当我在终端中执行call {js node call
时,我看到无数()完成后,然后检查()运行。这意味着 nodejs是同步吗?为什么?谁能帮我解答一下?非常感谢你!
答案 0 :(得分:3)
当你调用 call.countless()时,它正在执行该函数,但是内部没有任何阻塞I / O.因此运行时正忙于进行循环操作。如果您已编写任何阻塞I / O操作,那么您将看到NODE JS的异步特性。
for循环完成后,Interpreter转到第二个函数。
答案 1 :(得分:2)
node.js使用V8 Javascript引擎,它一个接一个地执行Javascript同步行。如果您在问题中使用countless
和check
方法编写顺序编码语句,那么这些语句就像在几乎任何其他编程语言中一样同步执行。
这是来自https://nodejs.org/en/的node.js描述的一部分。
Node.js使用事件驱动的非阻塞I / O模型 轻巧高效。
我认为,这比描述node.js是异步的更好,因为它更好地描述了它实际上做了什么。
只有使用某些外部接口(如网络)的真正异步操作才会在node.js中实现非阻塞。在这种情况下,调用非阻塞函数会启动操作,然后在下一行Javascript上继续执行Javascript。当非阻塞操作在将来某个时间完成时,会在事件队列中插入一个事件,当V8引擎完成执行当前执行线程时,可以从事件队列中提取该事件并调用回调
您无法在纯Javascript中从头开始编写真正的异步操作(实际代码在后台执行)。您需要外部接口(例如网络,文件I / O等等)的帮助才能创建实际的异步操作。您可以使用计时器模拟一个,但实际上并不是异步的,因为在后台实际上没有执行任何操作。计时器只是改变了运行时间(他们实际上并没有与你的Javascript执行同时工作)。
这是node.js中的异步操作示例:
var fs = require('fs');
console.log("one");
fs.readFile('temp.txt', function(err, data) {
if (err) {
console.log(err);
} else {
console.log("got data");
}
});
console.log("two");
这将生成以下输出:
one
two
got data
fs.readFile()
操作实际上是异步的。在您调用它之后,它会在后台运行,而后续语句中的其余Javascript将继续执行。当它完成时,将来的某个时候,它将使用错误或数据调用它的回调。
答案 2 :(得分:1)
节点本身不是异步的,它只是使用事件循环作为主要构造。事件循环的迭代是同步执行的,就像任何其他编程语言一样。
此处的示例根本不使用异步代码。仅仅因为某些东西在回调中并不一定意味着它是异步的(否则map
将是异步的)。您只是在这里使用高阶函数。
尝试将这两者放在个人setTimeout
中;调用顺序将无法保证。
节点保证运行完成(即,除非throws
直到第一个return
语句,否则将完全执行任何函数),因此任何同步代码将按照它的顺序执行书面 - 就像任何其他命令式语言一样。但是,任何I / O操作或使用Promise
之类的操作都会将其回调添加到任务队列中以便将来某个时间点执行,因此无法保证其执行顺序。
请注意,NodeJS是单线程的,并且大for
个循环将耗尽该单个线程,因为它是一个CPU绑定操作,因此在执行像这样的计算繁重的事情时要小心,因为您将挂起整个应用程序。对于计算量很大的东西,你可以屈服于使用另一种更适合这种事情的语言编写的子进程(使用child_process
模块)。