Reputation: 5622
I want to write a small worker app in node.js.
This app would read from AWS-SQS, process the data in some way, and spit it out to another AWS-SQS.
So far I have written:
while(true){
readFromQueue()
.then(transform)
.then(writeToQueue);
}
function transform(data) {
console.log("> transforming...");
//transformation logic
return data;
}
//TODO: need to remove message from queue after read!
function readFromQueue() {
// var params = {
// QueueUrl: 'STRING_VALUE',
// WaitTimeSeconds: 2
// };
// return new Promise(function(resolve, reject) {
// sqs.receiveMessage(params, function(err, data) {
// if (err) reject(err);
// else resolve(data);
// });
// });
return new Promise(function(resolve, reject) {
console.log("> reading from queue...");
resolve({ data : "world" });
});
}
function writeToQueue(data) {
// var params = {
// MessageBody: data,
// QueueUrl: 'STRING_VALUE',
// };
// sqs.sendMessage(params, function(err, data) {
// if (err) console.log(err, err.stack);
// else console.log(data);
// });
console.log("> writing to queue...");
console.log(">> " + data);
}
As you can see everything is set up for AWS, but when I run it locally for the time being, I would just have some mock stuff inside, until I actually get my transformation logic tested etc...
The problems I have are:
So am I doing something wrong? I can understand that since promises are async, my while loop will go crazy and create thousands of them, so that concerns me... Nevertheless I want to initiate another loop once the previous read->transform->write has been finished. Is there some other pattern I should use here? Or just block and wait for readFromQueue to end...
--EDIT--
It does execute everything if not wrapped in while(true):
readFromQueue()
.then(transform)
.then(writeToQueue);
I also understand that since while(true) is being executed, it will essentially block the thread, and therefore the promise is not resolved. So is there a way around it?
Upvotes: 3
Views: 4739
Reputation: 1167
I also ran into a similar issue (see setTimeout issue trying to wait for execution of async).
I've learned the lesson of sync patterns to be avoided in javascript and so i think your code could be rewritten with something similar:
function queueLooping(loopExitConditionPromise) {
var blockingGuard = { done: false };
loopExitConditionPromise.then(function () {
blockingGuard.done = true;
});
return loopingSequence;
var loopingSequence = function() {
readFromQueue()
.then(transform)
.then(writeToQueue);
if(!blockingGuard.done)
loopingSequence();
else
return;
};
var readFromQueue = function () {
console.log("> reading from queue...");
// ...
}
var transform = function (data) {
console.log("> transforming...");
// ...
}
var writeToQueue = function (data) {
console.log("> writing to queue...");
// ...
}
}
Upvotes: 0
Reputation: 5622
After evaluating all answers in here, I tried deasync, which did the job just fine :)
Nevertheless, I decided to go with mido22 answer above, just because I didn't want a plugin that is fiddling with node's event-loop.
Upvotes: 0
Reputation: 8423
Instead of this:
while(true){
readFromQueue()
.then(transform)
.then(writeToQueue);
}
Can't you use a recursive function? Something like this:
function getData(){
return readFromQueue()
.then(transform)
.then(function(data){
writeToQueue(data);
getData();
});
}
getData(); //Just to get it starting.
Upvotes: 0
Reputation: 25034
I am falling back to my setInterval
way. I know you said that reading queue has to start immediately after the writing is finished, but 10ms isn't much of delay if you ask me.
function someFunc(){
if(readingQueue) return;
readingQueue = true;
return readFromQueue()
.then(transform)
.then(writeToQueue)
.catch(someErrorHandler)
.then(function(){
readingQueue=false;
})
}
var readingQueue = false;
setInterval(someFunc, 10);
Upvotes: 5