在 Node.js 中编写非阻塞函数的正确方法 [英] Correct way to write a non-blocking function in Node.js

查看:27
本文介绍了在 Node.js 中编写非阻塞函数的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个返回 Promise 的简单函数,因此应该是非阻塞的(在我看来).不幸的是,该程序似乎停止等待 Promise 完成.我不确定这里有什么问题.

I wrote a simple function that returns Promise so should be non-blocking (in my opinion). Unfortunately, the program looks like it stops waiting for the Promise to finish. I am not sure what can be wrong here.

function longRunningFunc(val, mod) {
    return new Promise((resolve, reject) => {
        sum = 0;
        for (var i = 0; i < 100000; i++) {
            for (var j = 0; j < val; j++) {
                sum += i + j % mod
            }
        }
        resolve(sum)
    })
}

console.log("before")
longRunningFunc(1000, 3).then((res) => {
    console.log("Result: " + res)
})
console.log("after")

输出看起来像预期的:

before     // delay before printing below lines
after
Result: 5000049900000

但是程序在打印第二行和第三行之前会等待.您能解释一下先打印之前"和之后"然后(一段时间后)打印结果的正确方法吗?

But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?

推荐答案

在 Promise 中包装代码(就像您所做的那样)不会使其成为非阻塞的.Promise 执行器函数(您传递给 new Promise(fn) 的回调被同步调用并会阻塞,这就是您看到获取输出延迟的原因.

Wrapping code in a promise (like you've done) does not make it non-blocking. The Promise executor function (the callback you pass to new Promise(fn) is called synchronously and will block which is why you see the delay in getting output.

事实上,没有办法创建自己的非阻塞的纯 Javascript 代码(就像你所拥有的那样),除非将它放入子进程中,使用 WorkerThread,使用一些创建新线程的第三方库Javascript 或为线程使用新的实验性 node.js API.常规 node.js 以阻塞和单线程方式运行您的 Javascript,无论它是否包含在 Promise 中.

In fact, there is no way to create your own plain Javascript code (like what you have) that is non-blocking except putting it into a child process, using a WorkerThread, using some third party library that creates new threads of Javascript or using the new experimental node.js APIs for threads. Regular node.js runs your Javascript as blocking and single threaded, whether it's wrapped in a promise or not.

您可以使用诸如 setTimeout() 之类的东西来更改何时";您的代码运行,但无论何时运行,它仍然会阻塞(一旦它开始执行,其他任何东西都无法运行,直到它完成).node.js 库中的异步操作都使用某种形式的底层原生代码,允许它们异步(或者它们只是使用其他 node.js 异步 API,它们本身使用原生代码实现).

You can use things like setTimeout() to change "when" your code runs, but whenever it runs, it will still be blocking (once it starts executing nothing else can run until it's done). Asynchronous operations in the node.js library all use some form of underlying native code that allows them to be asynchronous (or they just use other node.js asynchronous APIs that themselves use native code implementations).

但是程序在打印第二行和第三行之前会等待.你能解释一下什么是获得之前"的正确方法吗?和之后"先打印然后(一段时间后)结果?

But the program waits before printing second and third lines. Can you explain what should be the proper way to get "before" and "after" printed first and then (after some time) the result?

正如我上面所说,在 promise executor 函数中包装东西不会使它们异步.如果你想移位"事情运行的时间(认为它们仍然是同步的),你可以使用 setTimeout(),但这并没有真正使任何非阻塞,它只是让它稍后运行(仍然阻塞运行).

As I said above, wrapping things in promise executor function doesn't make them asynchronous. If you want to "shift" the timing of when things run (thought they are still synchronous), you can use a setTimeout(), but that's not really making anything non-blocking, it just makes it run later (still blocking when it runs).

所以,你可以这样做:

function longRunningFunc(val, mod) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            sum = 0;
            for (var i = 0; i < 100000; i++) {
                for (var j = 0; j < val; j++) {
                    sum += i + j % mod
                }
            }
            resolve(sum)
        }, 10);
    })
}

这将重新安排耗时的 for 循环稍后运行并可能出现"是非阻塞的,但它实际上仍然阻塞 - 它只是稍后运行.要使其真正实现非阻塞,您必须使用前面提到的技术之一将其从 Javascript 主线程中取出.

That would reschedule the time consuming for loop to run later and might "appear" to be non-blocking, but it actually still blocks - it just runs later. To make it truly non-blocking, you'd have to use one of the techniques mentioned earlier to get it out of the main Javascript thread.

在 node.js 中创建实际非阻塞代码的方法:

Ways to create actual non-blocking code in node.js:

  1. 在单独的子进程中运行它,并在完成后收到异步通知.
  2. 在 node.js v11 中使用新的实验性工作线程
  3. 为 node.js 编写您自己的本机代码插件,并在您的实现中使用 libuv 线程或操作系统级线程(或其他操作系统级异步工具).
  4. 构建在先前存在的异步 API 之上,并且没有在主线程中花费很长时间的您自己的代码.

这篇关于在 Node.js 中编写非阻塞函数的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆