Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在完成异步任务之前阻止事件循环_Javascript_Node.js_Asynchronous_Redis_Event Loop - Fatal编程技术网

Javascript 如何在完成异步任务之前阻止事件循环

Javascript 如何在完成异步任务之前阻止事件循环,javascript,node.js,asynchronous,redis,event-loop,Javascript,Node.js,Asynchronous,Redis,Event Loop,假设我们有一个web服务器,它接收http请求并发送响应。它有许多端点,包括这个端点 /task应该有一些异步任务,比如从Redis读取/写入,我想阻止事件循环,直到这些任务完成。我知道这是不合理的,因为事件循环还需要继续工作以接收Redis的事件。因此,我正在考虑将此逻辑放在一个单独的脚本中,并使用child\u process.spawnSync执行并等待它并阻止当前事件循环。这个解决方案会起作用,但我的问题是我的逻辑和异步任务比本示例中提到的更复杂,它们与当前脚本有依赖关系,并且它们是框架

假设我们有一个web服务器,它接收http请求并发送响应。它有许多端点,包括这个端点

/task
应该有一些异步任务,比如从
Redis
读取/写入,我想阻止事件循环,直到这些任务完成。我知道这是不合理的,因为事件循环还需要继续工作以接收
Redis
的事件。因此,我正在考虑将此逻辑放在一个单独的脚本中,并使用
child\u 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);

你应该研究一下如何使用它。您必须重新编写所有适用的代码才能使用Promissions或使用为您这样做的库

您的主要功能可能如下所示:

(async function main(){
 try{

 await taskFunction();
 await backupGetFunction();
 await backupSetFunction();
  res.send('I am done');

 } catch (error){
  throw error;
 }; 

})();
一切都将按顺序执行,最后,它将按预期发送“我完成了”

此解决方案背后的复杂性在于,任何依赖于主函数的函数都需要使用承诺来保持流异步

例如,您的备份功能最初可能是:

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

承诺作为主要异步/等待函数的指南,以便它知道异步函数何时完成。

您应该研究如何使用。您必须重新编写所有适用的代码才能使用Promissions或使用为您这样做的库

您的主要功能可能如下所示:

(async function main(){
 try{

 await taskFunction();
 await backupGetFunction();
 await backupSetFunction();
  res.send('I am done');

 } catch (error){
  throw error;
 }; 

})();
一切都将按顺序执行,最后,它将按预期发送“我完成了”

此解决方案背后的复杂性在于,任何依赖于主函数的函数都需要使用承诺来保持流异步

例如,您的备份功能最初可能是:

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');
  });
 });
}; 
承诺作为主要异步/等待函数的指南,以便它知道异步函数何时完成。

您可以使用

redis.getAsync('backup')
.then(res => {

// ...... Do some changes to the backup data
 return redis.set('backup', backup)
})
.then(()=>res.send('I\'m done'))

注意:如果使用异步/等待功能,则至少需要有节点v7及以上。或者——运行您可以使用的节点时的harmony async Wait标志

redis.getAsync('backup')
.then(res => {

// ...... Do some changes to the backup data
 return redis.set('backup', backup)
})
.then(()=>res.send('I\'m done'))


注意:如果使用异步/等待功能,则至少需要有节点v7及以上。或者——运行节点时使用harmony async Wait标志

有什么建议吗?
,有。不要堵住。不清楚为什么在你的描述中你也需要1.我为什么需要阻止并不重要,问题是如何阻止。无论如何,我需要将一些会话状态备份到Redis中,并防止接收到可能使这些数据无效的事件,直到将当前会话状态存储到Redis中,然后继续处理其间接收到的事件,这就是为什么我需要阻止事件循环,让那些事件排队并防止竞争条件。你可以在不阻塞主线程的情况下完成所有这些。不管怎么说,你有什么建议,那是我的。如果这是一个多用户网站,这样做会使它瘫痪。我不认为阻止事件循环也是一种选择。也许升起一面全球旗帜或使用其他机制对你有用。例如,
//立即阻止事件循环
->
global.event\u loop\u BLOCKED=true
。现在使用此变量返回类似“服务器当前正忙”的内容,响应与Redis交互的所有请求,当您完成作业时,只需
global.EVENT\u LOOP\u BLOCKED=false
那么,node.js中没有好的解决方案来自于阻止事件循环,因此,你应该告诉我们你试图解决的真正问题,然后我们可以帮助你更好地找到一个好的解决方案。这里是一个XY问题,您只是用解决方案描述了一个问题,但该解决方案是一条死胡同,因为您没有描述实际问题,我们无法帮助您。
有什么建议吗?
,是的。不要堵住。不清楚为什么在你的描述中你也需要1.我为什么需要阻止并不重要,问题是如何阻止。无论如何,我需要将一些会话状态备份到Redis中,并防止接收到可能使这些数据无效的事件,直到将当前会话状态存储到Redis中,然后继续处理其间接收到的事件,这就是为什么我需要阻止事件循环,让那些事件排队并防止竞争条件。你可以在不阻塞主线程的情况下完成所有这些。不管怎么说,你有什么建议,那是我的。如果这是一个多用户网站,这样做会使它瘫痪。我不认为阻止事件循环也是一种选择。也许升起一面全球旗帜或使用其他机制对你有用。例如,
//立即阻止事件循环
->
global.event\u loop\u BLOCKED=true
。现在使用此变量返回类似“服务器当前正忙”的内容,响应与Redis交互的所有请求,当您完成作业时,只需
global.EVENT\u LOOP\u BLOCKED=false
那么,node.js中没有好的解决方案来自于阻止事件循环,因此,你应该告诉我们你试图解决的真正问题,然后我们可以帮助你更好地找到一个好的解决方案。这里是一个XY问题,您只是用解决方案描述了一个问题,但该解决方案是一条死胡同,因为您没有描述实际问题,我们无法帮助您。根据您的请求进行更新,egon12.我认为
async函数备份示例
不需要
async
关键字,因为它已经返回
Promise
。根据您的请求更新,egon12。我认为
async函数备份示例
不需要