假设我们有一个网络服务器接收 HTTP 请求并发回响应。它有很多端点,包括这个
/task
应该有一些异步任务,比如从 Redis
读取/写入,我想阻塞事件循环,直到这些任务完成。我知道这是不合理的,因为事件循环还需要继续工作以接收 Redis
的事件。所以我正在考虑将这个逻辑放在一个单独的脚本中并使用 child_process.spawnSync
来执行并等待它并阻止当前事件循环。这个解决方案可行,但我的问题是我的逻辑,异步任务比这个示例中提到的更复杂,它们依赖于当前脚本并且它们是框架的一部分,将它们分离到一个单独的脚本并不容易.有什么建议吗?
var express = require('express');
var app = express();
var redis = require('./redis');
// Block the event loop until finish doing some async tasks
app.get('/task', function(req, res) {
// Block the event loop now
redis.get('backup', function(error, backup) {
// ...... Do some changes to the backup data
redis.set('backup', backup, function(error, result) {
// Unblock the event loop now
res.send('I am done');
});
});
});
// To check if the event loop is really blocked
counter = 0;
setInterval(() => { console.log(counter++) }, 100);
app.listen(5000);
最佳答案
您应该考虑使用 async/await .您将不得不重新编写所有适用的代码以使用 Promises 或使用为您执行此操作的库。
您的主要功能可能如下所示;
(async function main(){
try{
await taskFunction();
await backupGetFunction();
await backupSetFunction();
res.send('I am done');
} catch (error){
throw error;
};
})();
一切都会按顺序执行,最后会按预期重新发送“我完成了”。
此解决方案背后的复杂性在于,任何依赖于 main 函数的函数都需要使用 promises 以保持流程异步。
例如,您的备份功能最初可能是;
function backupExample(){
fs.copyFile('source.txt', 'destination.txt', (err) => {
if (err) throw err;
console.log('source.txt was copied to destination.txt');
});
};
当它必须转换成下面的形式才能与 async/await 一起工作时;
function backupExample(){
return new Promise((resolve, reject) => {
fs.copyFile('source.txt', 'destination.txt', (err) => {
if (err) reject(err);
resolve('source.txt was copied to destination.txt');
});
});
};
promises 充当主要 async/await 函数的指南,因此它知道异步函数何时完成。
关于javascript - 如何阻止事件循环直到完成运行异步任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46994508/