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

查看:89
本文介绍了在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")

输出看起来像预期的一样:

The output looks like expected:

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执行程序功能(传递给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线程的第三方库将其放入子进程之外,没有其他方法可以创建自己的无阻塞的普通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 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,并在实现(或其他OS级异步工具)中使用libuv线程或OS级线程.
  4. 在先前存在的异步API的基础上构建,并且没有自己的代码在主线程中花费很长时间.

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

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