首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Nodejs实际上是异步的吗?

Nodejs实际上是异步的吗?
EN

Stack Overflow用户
提问于 2016-05-21 18:13:45
回答 3查看 92关注 0票数 1

我看到了这个帖子:https://www.codementor.io/nodejs/tutorial/manage-async-nodejs-callback-example-code,在运行代码之后,我确认nodejs是异步的。但是,我创建了2个js文件来再次测试nodejs的异步特性。

文件1:callback_example.js

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
var call = require('./callback_example');

call.countless(function(x){
    console.log(x);
});

call.check(function(x){
    console.log(x);
});

当我以node call的形式在终端中执行node call时,在无数()完成之后,我看到了,然后检查()运行。这意味着nodejs是同步的?为什么?有人能帮我回答这个问题吗?非常感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-21 18:18:47

node.js使用V8 Javascript引擎,并依次执行Javascript同步行。如果您在问题中编写了顺序编码语句,比如在countlesscheck方法中,那么这些语句将同步执行,就像在其他编程语言中一样。

以下是来自node.js的https://nodejs.org/en/描述的一部分。

Node.js使用事件驱动的、无阻塞的I/O模型,使其轻量级和高效。

我认为,这比仅仅说node.js是异步的要好得多,因为它更好地描述了它实际上所做的事情。

在node.js中,只有真正使用诸如网络之类的外部接口的真正异步操作才是真正的非阻塞操作。在这种情况下,调用非阻塞函数将启动操作,然后在Javascript的下一行继续执行Javascript。当非阻塞操作在未来一段时间内完成时,事件将插入到事件队列中,当V8引擎完成当前执行线程时,可以从事件队列中提取该事件并调用回调。

您不能用纯Javascript从头开始编写真正的异步操作(在后台执行实际代码)。您需要外部接口的帮助(例如网络、文件I/O等)。为了创建一个实际的异步操作。您可以用计时器模拟一个,但这实际上并不是异步的,因为在后台没有任何实际执行。计时器只需改变运行时间(它们实际上并不与Javascript执行并行工作)。

下面是node.js中异步操作的一个示例:

代码语言:javascript
运行
复制
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");

这将产生以下输出:

代码语言:javascript
运行
复制
one
two
got data

fs.readFile()操作实际上是异步的。调用它之后,它会在后台完成它的工作,而后面语句中的Javascript的其余部分则继续执行。当它完成时,在将来的某个时候,它将用一个错误或数据调用它的回调。

票数 2
EN

Stack Overflow用户

发布于 2016-05-21 18:23:37

当您调用call.countless()时,它正在执行该函数,但是在该函数中没有阻塞I/O。所以Runtime忙于执行循环操作。如果您编写了任何阻塞I/O操作,那么您就会看到节点JS的异步特性。

例如阻塞I/O操作:文件读写、TimeOut、DB操作、Ajax调用

在for循环完成后,解释器将转到第二个函数。

票数 3
EN

Stack Overflow用户

发布于 2016-05-21 18:18:32

节点本身并不是异步的,它只是使用事件循环作为主要构造。事件循环的迭代是同步执行的,就像任何其他编程语言一样。

这里的示例根本不使用异步代码。仅仅因为回调中有东西并不一定意味着它是异步的(例如,map将是异步的)。你只是在这里使用高阶函数。

尝试将这两种方法都放在单独的setTimeout中;调用顺序不会得到保证。

节点保证运行到完成(也就是说,任何函数都将完全执行,除非它是throws,直到第一个return语句),所以任何同步代码都将按照编写的顺序执行--就像任何其他命令式语言一样。但是,任何I/O操作或类似于使用Promise的事情都会将它们的回调添加到任务队列中,以便在将来的某个时候执行,因此它们的执行顺序无法保证。

请注意,NodeJS是单线程的,大型的for循环会占用这个单线程,因为它是一个与CPU绑定的操作,所以在执行这种计算量很大的操作时要小心,因为您将挂起整个应用程序。对于计算量很大的东西,可以使用用另一种语言编写的子进程(使用child_process模块)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37366477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档