微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript – 在node.js中编写非冒号函数的正确方法

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

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

但程序在打印第二行和第三行之前等待.你能解释一下,首先打印“之前”和“之后”,然后(经过一段时间)结果的正确方法是什么?

解决方法:

在承诺中包装代码(就像你已经完成的那样)并不会使它成为非阻塞代码. Promise执行程序函数(传递给新Promise(fn)的回调被同步调用,并将阻止这就是为什么你看到输出的延迟.

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

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

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执行函数中包装东西不会使它们异步.如果你想“改变”事物运行的时间(认为它们仍然是同步的),你可以使用setTimeout(),但这并不是真正做任何非阻塞,它只是让它运行得更晚(当它运行时仍然阻塞)运行).

所以,你可以这样做:

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);
    })
}

这将重新安排循环运行以后的耗时,并且可能“看起来”是非阻塞的,但它实际上仍然阻塞 – 它只是稍后运行.要使其真正无阻塞,您必须使用前面提到的技术之一将其从主Javascript线程中删除.

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐