I'm trying to create a function that builds a queue from an array of objects and then processes each object by calling a number of functions.
The processing functions are asynchronous functions which, prior to needing to queue, I'd implemented using the async/await pattern. I think this is necessary as each relies on the output of the previous and I don't want to have a tonne of nested promise.then's
i.e. previously I had:
await Promise.all(messages.map(async(message) => {
let activity = await activityController.getActivity(message.activityId);
let url = await SMSController.getUrl(message.Token);
let smsSendResult = await SMSController.sendSMS(messageString, activity.mobileNo);
// etc...
}
Now what I want to be able to do is:
let queue = async.queue((message, done) => {
let activity = await activityController.getActivity(message.activityId);
let smsSendResult = await SMSController.sendSMS(messageString, activity.mobileNo);
// etc...
}
messages.forEach((message) => {
queue.push(message);
})
I have the problem though that this results in
SyntaxError: await is only valid in async function
And I can't seem to quite get my head around how to get past this.
You're looking for async.series
, not async.queue
:
series(tasks, callbackopt)
Run the functions in the
tasks
collection in series, each one running once the previous function has completed.
So just following the docs:
const messageCallbacks = messages.map(function(msg) {
return async function(callback) {callback(await handleMessage(msg));
});
async.series(messageCallbacks,
// optional callback
function(err, results) {
// results is now equal to whatever handleMessage resolves to
});
Without async:
async function asyncMessageQueue(messages) {
const results = [];
for(var i=0,l=messages.length; i<l; ++i) {
results.push(await handleMessage(messages[i]));
}
return results;
}
async function handleMessage(message) {
let activity = await activityController.getActivity(message.activityId);
let url = await SMSController.getUrl(message.Token);
let smsSendResult = await SMSController.sendSMS(messageString, activity.mobileNo);
// rest of the code
};
This also allows you to provide the next message with any previous results:, just change await handleMessage(messages[i])
to await handleMessage(messages[i], results)
and then:
async function handleMessage(message, prevResults) {
// rest of the code
};
I found the asyncify function in the async module which allows me to do this:
var queue = async.queue(async.asyncify(async (message, done) => {
let url = await SMSController.getUrl(message.token);
// etc...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With