Reputation: 22959
How can I process a series of messages that come through to a function, in the order that they come, when the functions to process the messages are operating on the messages asynchronously?
An example:
var processMessage = function(msg) {
switch (msg.action) {
case "doFoo":
this.processFoo(()=> {
// `foo` is done processing
});
break;
case "doBar":
this.processBar(()=> {
// `bar` is done processing
});
break;
case "doBaz":
this.processBaz(()=> {
// `baz` is done processing
});
break;
}
}
Is there any de-facto/standard solution to this kind of problem?
Upvotes: 2
Views: 946
Reputation: 707696
Here's a general scheme:
You trigger processing of new messages at two points. First, when a new messages arrives and you aren't already processing a message and second when the processing of some other message completes, you check if anything else was added to the queue while you were processing.
You maintain an inProcessing
type flag so you don't inadvertently start processing an incoming message when another message is already in the middle of being processed (this forces the serial execution you requested).
You have to rigorously deal with error conditions so the flag never gets stuck and so your queue processing never gets stalled.
In pseudo code (assuming these are methods on a queue object which contains an array as the queue):
addQueue: function(msg) {
if (!this.inProcess) {
// not currently processing anything so just process the message
this.processMessage(msg);
} else {
this.queue.push(msg);
}
},
processMessage: function(msg, completeFn) {
var self = this;
// must set this flag before going async
self.inProcess = true;
// asynchronously process this message
someAsyncProcessing(msg, function(err) {
self.inProcess = false;
if (completeFn) {
completeFn(err);
}
// see if anything else is in the queue to process
if (self.queue.length) {
// pull out oldest message and process it
var msg = self.queue.shift();
self.processMessage(msg);
}
});
}
Upvotes: 2