javascript - How to write a Promise wrapper around Web Workers API? - Stack Overflow

I am writing a library which makes use of Web Workers. The consumer of the library should not see any o

I am writing a library which makes use of Web Workers. The consumer of the library should not see any of the Web Worker stuff and should instead get returned a Promise from the public methods of this library like this:

// consumer.js

const api = new Api();

api.doCalculation(input1).then(data => console.log(data));
api.doCalculation(input2).then(data => console.log(data));
api.doCalculation(input3).then(data => console.log(data));

In my library code I have a class which wraps the Web Worker logic. In the constructor I create the worker and set the "message" event listener, listening for ining data from the worker thread. Also in this class there is a doCalculation(input) method which is public to the consumer of the library. It takes the input and sends it to the worker thread to perform the actual calculation.

// api.js

class Api {
  constructor() {
    this.worker = new Worker('worker.js');

    this.worker.addEventListener('message', (e) => {

      // I want to return this e.data from the doCalculation method
      console.log(e.data);
    });
  }

  doCalculation(input) {
    this.worker.postMessage({input: input});

    // I want to return a Promise from this method,
    // holding the result e.data
  }
}

My question now is, how can I return a Promise from the doCalculation method holding e.data?

My first intend was something like this which obviously doesn't work because a new "message" event listener is created with every call to doCalculation.

// api.js

class Api {
  constructor() {
    this.worker = new Worker('worker.js');
  }

  doCalculation(input) {
    this.worker.postMessage({input: input});
    return new Promise((resolve => {
      this.worker.addEventListener('message', (e) => {
        resolve(e.data);
      });
    }))
  }
}

All the code examples here are simplified to only make my point clear.

I would be thankful for any hints into the right direction!

I am writing a library which makes use of Web Workers. The consumer of the library should not see any of the Web Worker stuff and should instead get returned a Promise from the public methods of this library like this:

// consumer.js

const api = new Api();

api.doCalculation(input1).then(data => console.log(data));
api.doCalculation(input2).then(data => console.log(data));
api.doCalculation(input3).then(data => console.log(data));

In my library code I have a class which wraps the Web Worker logic. In the constructor I create the worker and set the "message" event listener, listening for ining data from the worker thread. Also in this class there is a doCalculation(input) method which is public to the consumer of the library. It takes the input and sends it to the worker thread to perform the actual calculation.

// api.js

class Api {
  constructor() {
    this.worker = new Worker('worker.js');

    this.worker.addEventListener('message', (e) => {

      // I want to return this e.data from the doCalculation method
      console.log(e.data);
    });
  }

  doCalculation(input) {
    this.worker.postMessage({input: input});

    // I want to return a Promise from this method,
    // holding the result e.data
  }
}

My question now is, how can I return a Promise from the doCalculation method holding e.data?

My first intend was something like this which obviously doesn't work because a new "message" event listener is created with every call to doCalculation.

// api.js

class Api {
  constructor() {
    this.worker = new Worker('worker.js');
  }

  doCalculation(input) {
    this.worker.postMessage({input: input});
    return new Promise((resolve => {
      this.worker.addEventListener('message', (e) => {
        resolve(e.data);
      });
    }))
  }
}

All the code examples here are simplified to only make my point clear.

I would be thankful for any hints into the right direction!

Share Improve this question asked Aug 14, 2019 at 13:44 user11276880user11276880
Add a ment  | 

1 Answer 1

Reset to default 7

For sure you could store resolve somewhere, e.g. in an object:

 this.resolvers = {};
 this.count = 0; // used later to generate unique ids

Then for each task sent to the webworker, create a unique id, and store the promise resolver there

 const id = this.count++;
 // Send id and task to WebWorker
 return new Promise(resolve => this.resolvers[id] = resolve);

Then when the webworker sends a message, get the id from it, and resolve the stored promise:

 this.resolvers[ id ](data);
 delete this.resolvers[id]; // Prevent memory leak

That way (1) you only need to register one handler, (2) multiple tasks can be handled at the same time by the webworker and (3) You can easily determine which tasks are running on the webworker by checking the Object.keys(this.resolvers).

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745242851a4618275.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信