Reputation: 19651
Let's assume that we have a web server that receives http requests and send responses back. It has many endpoints including this one
/task
should has some async tasks like reading/writing from Redis
, I want to block the event loop until those tasks are finished. I know it is not reasonable because the event loop needs also to keep working to receive the events for Redis
. So I am thinking about putting this logic in a separate script and use child_process.spawnSync
to execute and wait for it and block the current event loop. This solution will work but my problem is my logic and the async tasks are more complex than what mentioned in this sample, they have dependencies to the current script and they are part of the framework, it is not easy to separate them to a separated script. Any suggestions ?
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);
Upvotes: 0
Views: 866
Reputation: 31
You should look into using async/await. You would have to re-write all applicable code to work with Promises or use a library that does so for you.
Your primary function might look something like this;
(async function main(){
try{
await taskFunction();
await backupGetFunction();
await backupSetFunction();
res.send('I am done');
} catch (error){
throw error;
};
})();
Everything will be executed in order and at the end, it will res.send 'I am done' as expected.
The complexity behind this solution is that any functions that rely on the main function will need to be using promises in order to keep the flow asynchronous.
As an example, your backup function might initially be;
function backupExample(){
fs.copyFile('source.txt', 'destination.txt', (err) => {
if (err) throw err;
console.log('source.txt was copied to destination.txt');
});
};
When it must be converted to the following to work with 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');
});
});
};
The promises act as guidance to the primary async/await function so it knows when async functions have completed.
Upvotes: 2
Reputation: 336
you can use.
redis.getAsync('backup')
.then(res => {
// ...... Do some changes to the backup data
return redis.set('backup', backup)
})
.then(()=>res.send('I\'m done'))
or
let backup = await redis.getAsync('backup');
// ...... Do some changes to the backup data
redis.set('backup', backup);
res.send('I\'m done');
note if you use async/await features you need to have at least node v7 and up. or --harmony-async-await flag when running the node
Upvotes: 0