Async: How to queue es6 async functions

Created on 12 May 2017  ·  4Comments  ·  Source: caolan/async

So I have a couple of async/await functions and I'd like to queue them. They're fired "randomly" on specific websocket events but they have to run one after the other. So I'm testing this with this code.

const aida = {
  async launch() {
    await someFunction();
  },
  async login() {
    await Auth();
    await UserSettings();
  },
  async goToMonth() {
    await JumpToDefaultMonth();
  }
};


const q = async.queue(function(task, callback) {
  console.log('hello ' + task.name);
  callback();
}, 1);

q.drain = function() {
  console.log('all items have been processed');
};

q.push(aida.launch());
q.push(aida.login());
q.push(aida.goToMonth());

I'd expect that for example login() only runs after launch() in finished.
Am I doing something wrong or is this library not the right one for me?

question queue

Most helpful comment

@codeofsumit sorry, I realized my previous comment was a little misguide, I got queue confused with a different function. Hopefully I can clarify.

  1. How does the queue start? Didn't seem to start after the first push

queue should start when it gets a task, i.e. when you call q.push. Could you provide a code sample? The above code ran for me.

Side note: If you are using es7 async functions with async and transpiling your code, you will have to wrap them in async.asyncify. See this comment for more info.

  1. How can I pass parameters to the functions?

This is where I got confused. The worker you pass to async.queue when you create it, is responsible for processing the task. If you need to run launch, login, and goToMonth for each event from the websocket, you can just put in the worker function. For example,

const q = async.queue(function(task, callback) {
  async.series([
    async function() {
      await aida.launch(task.foo, task.boo);
    },
    async function() {
      await aida.login(task.baz);
    },
    // etc...
  ], callback);
}, 1);

// on a websocket event
q.push({foo: websocketData.foo, bar: websocketData.bar, baz: websocketData.baz});

Otherwise, if you need to queue functions, it's a little hacky, but you could something along the lines of:

const q = async.queue(async function(task) {
  await task.func.apply(null, task.args);
}, 1);

// on a websocket event
q.push({func: aida.launch, args: [websocketData.foo, websocketData.bar]});
q.push({func: aida.login, args: [websocketData.baz]});
q.push({func: aida.goToMonth, args: []});

Hopefully this is a little clearer.

All 4 comments

Hi @codeofsumit, thanks for the question!

From looking at your code, I think the issue is with the last three lines. You're invoking the functions, and pushing their return value into the queue as opposed to pushing the functions into the queue. See the QueueObject docs for more info about q.push. Try changing them to:

q.push(aida.launch);
q.push(aida.login);
q.push(aida.goToMonth);

Since you have a concurrency of 1, the queue will only process login after launch finished.

@hargasinski I thought so and tried that but that brings two new questions:

  1. How does the queue start? Didn't seem to start after the first push
  2. How can I pass parameters to the functions?

@codeofsumit sorry, I realized my previous comment was a little misguide, I got queue confused with a different function. Hopefully I can clarify.

  1. How does the queue start? Didn't seem to start after the first push

queue should start when it gets a task, i.e. when you call q.push. Could you provide a code sample? The above code ran for me.

Side note: If you are using es7 async functions with async and transpiling your code, you will have to wrap them in async.asyncify. See this comment for more info.

  1. How can I pass parameters to the functions?

This is where I got confused. The worker you pass to async.queue when you create it, is responsible for processing the task. If you need to run launch, login, and goToMonth for each event from the websocket, you can just put in the worker function. For example,

const q = async.queue(function(task, callback) {
  async.series([
    async function() {
      await aida.launch(task.foo, task.boo);
    },
    async function() {
      await aida.login(task.baz);
    },
    // etc...
  ], callback);
}, 1);

// on a websocket event
q.push({foo: websocketData.foo, bar: websocketData.bar, baz: websocketData.baz});

Otherwise, if you need to queue functions, it's a little hacky, but you could something along the lines of:

const q = async.queue(async function(task) {
  await task.func.apply(null, task.args);
}, 1);

// on a websocket event
q.push({func: aida.launch, args: [websocketData.foo, websocketData.bar]});
q.push({func: aida.login, args: [websocketData.baz]});
q.push({func: aida.goToMonth, args: []});

Hopefully this is a little clearer.

uhh this looks very promising. Thank you for taking the time to explain it in such detail. Helps a lot!

Also: I noticed you're resolving issues in this repo VERY fast (not much open issues for such a popular library). 👍 very impressive - keep up the good work!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mjafarpour picture mjafarpour  ·  3Comments

ashoksahoo picture ashoksahoo  ·  3Comments

jairoGilC picture jairoGilC  ·  3Comments

cobya picture cobya  ·  5Comments

trvra picture trvra  ·  3Comments