gpt4 book ai didi

javascript - 如何正确地允许 Node js 有机会在我的无限 while 循环中运行其异步事件

转载 作者:行者123 更新时间:2023-11-29 09:40:32 24 4
gpt4 key购买 nike

每当我在位置 B 运行“save_to_db”函数时,它就会失败。

下面的代码显示了问题......


//location A

var i = 0;
while(true)
{

i++;
if(i == 100)
{

//location B

save_to_db(newUnit, 11214.1, 'TEST');
}

}


//location C

函数“save_to_db”在位置 A 和 C 工作正常。但在位置 B 失败。

我认为这是因为 while 循环是无限且同步的。因此,它不会给 Nodejs 运行事件循环的机会。在这种情况下,我们如何才能正确地让nodejs有机会运行其事件循环?

======================更新======================== ======

上面的代码是非常简单的代码版本。我有一个名为“db_util”的类/模块,它有两个方法:“save_to_db”和“read_from_db”。我认为由于这些方法使用了“mysql”模块,它们以异步方式访问数据库。但是我的 while true 循环阻塞了nodejs eventloop。因此 while 循环中的两个方法都没有机会被调用。

var mysql = require('mysql');
var db_util = function()
{}

db_util.prototype = {
save_to_db: function (neural_network, fitness, type) {
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'nodejstestdb'
});
connection.connect();
var addSql = 'INSERT INTO mytable(id, nn, type, fitness) VALUES(?,?,?,?)';
var addSqlParams = [null, neural_network, type, fitness];
connection.query(addSql, addSqlParams, function (err, result) {
if (err) {
console.log('[INSERT ERROR] - ', err.message);
return;
}
console.log('INSERT ID:', result);
});
connection.end();
},


read_from_db:function(){

var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'nodejstestdb'
});
connection.connect();

var sql = 'SELECT * FROM mytable ORDER BY fitness DESC';
connection.query(sql, function (err, result) {
if (err) {
console.log('[SELECT ERROR] - ', err.message);
return;
}
console.log(result);
var nn = result[0].nn;
neural_network = synaptic.Network.fromJSON(JSON.parse(nn));
return neural_network;
});
connection.end();
}
}

module.exports = db_util;


================ 由于答案而更新 2

let i = 0;
(function tick() {
++i;
if (i%100 == 0) {
save_to_db();
}
setTimeout(tick, 0); // Queue a callback on next(ish) event loop cycle
}());
let i = 0;
tick();

@T.J.克劳德先生,谢谢您的回答。但是上面的代码和下面的代码有什么区别?

var i = 0;

function tick() {
++i;
if (i%100 == 0) {
save_to_db();
}
setTimeout(tick, 0); // Queue a callback on next(ish) event loop cycle
}

tick();

最佳答案

As VLAZ says ,我想知道为什么你需要一个无限循环,而不仅仅是使用事件循环。

I think it is because the while loop is infinite and synchronized. Therefore it doesn't give nodejs chance to run its event loop.

是的,你完全正确。

如果不知道 save_to_db 的工作原理,就很难回答这个问题,但一般来说,您有三个选择:

  1. 使用一系列链式setTimeout(或setImmediate)回调。

    • 变化:您执行一个工作 block (例如,最多 100 次迭代),然后使用 setTimeout 安排下一个工作 block 。
  2. 使用async函数和await(如果save_to_db返回一个promise,或者可以修改为返回一个promise)。

  3. 使用worker thread ,当主线程应该执行 save_to_db 时,它会向主线程发送一条消息(然后工作线程的事件循环被阻塞并不会阻止主线程上 save_to_db 需要的事件)。 (我可能不会为此使用 worker 。)

<小时/>

#1 看起来大致如下:

let i = 0;
(function tick() {
++i;
if (i == 100) {
save_to_db();
}
setTimeout(tick, 0); // Queue a callback on next(ish) event loop cycle
}());

请注意,Node.js 对计时器进行速率限制,因此 setTimeout(tick, 0) 不一定会在下一次事件循环迭代中安排下一次调用。您可以使用setImmediate相反,因为它

Schedules the "immediate" execution of the callback after I/O events' callbacks.

例如,这段代码:

let i = 0;
let last = Date.now();
let sum = 0;
(function tick() {
++i;
sum += Date.now() - last;
if (i < 1000) {
last = Date.now();
setTimeout(tick, 0);
} else {
console.log(`Average: ${sum / i}`);
}
})();

报告我的 Linux 机器上安装的 Node v12.4 的平均运行时间为 1.155 毫秒。使用 setImmediate 的等效代码报告的平均时间仅为 0.004ms。

您在评论中说过您不明白如何以“ block ”的方式实现这一点。这是一个例子:

const chunkSize = 1000; // Or whatever
let i = 0;
(function chunk() {
const chunkEnd = i + chunkSize;
while (i++ < chunkEnd) {
if (/*time to save to the DB*/) {
// Note that we don't wait for it to complete, you've said it's
// okay not to wait and that it's okay if they overlap
save_to_db();
}
}
setImmediate(chunk, 0);
})();

这样做时,它会在主线程上完成大量工作,然后让出以允许处理 save_to_db 可能需要的任何 I/O 回调,然后继续进行。您可以对其进行一些优化,以便仅在它知道 save_to_db 仍有工作要做时才返回,但这可能是过度设计的。

<小时/>

#2 看起来大致如下:

(async () => {
try {
let i = 0;
while (true) {
if (i == 100) {
await save_to_db();
}
}
} catch (e) {
// Handle/report error
}
})();

#3 我将留给读者作为练习,但我可能不会为此使用工作人员。

关于javascript - 如何正确地允许 Node js 有机会在我的无限 while 循环中运行其异步事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56748318/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com