Skip to content
chetanism edited this page Jun 17, 2020 · 2 revisions

Getting back job results via Promise API

Use Case: This is mostly useful when you want to use the queue as a concurrency control. The idea here is to define a wrapper class that will have just a single instance to enqueue jobs and provides a simple API returning a promise that resolves or rejects depending on job fails or completes.

This may be useful to minimise the impact of using queue in your existing codebase e.g. const result = await foo(bar); changes to const result = await myQueue.addJob(() => foo(bar));

You can define a wrapper class for your queue

class MyJobQueue {
  private theQueue;
  private jobResolveRejectMap = new Map();

  constructor() {
    this.theQueue = queue(/* Your options */);

    this.theQueue.on('success', this.onJobComplete.bind(this));
    this.theQueue.on('error', this.onJobFailed.bind(this));
  }

  async addJob(job): Promise<any> {
    this.theQueue.push(job);
    return new Promise((resolve, reject) => {
      this.jobResolveRejectMap.set(job, { resolve, reject });
    });
  }

  onJobComplete(result, job) {
    const { resolve } = this.jobResolveRejectMap.get(job);
    this.jobResolveRejectMap.delete(job);
    resolve(result);
  }

  onJobFailed(error, job) {
    const { reject } = this.jobResolveRejectMap.get(job);
    this.jobResolveRejectMap.delete(job);
    reject(error);
  }
}

It can then be used as:

// You'll probably need just a single instance
const myQueue: MyJobQueue = new MyJobQueue();

const result = await myQueue.addJob(() => {
  return new Promise(resolve => {
    setTimeout(() => resolve(42), 100);
  });
})
// result === 42

Caveats:

  • To handle synchronous jobs the class may need a few tweaks.
Clone this wiki locally