developit / greenlet

🦎 Move an async function into its own thread.
https://npm.im/greenlet
4.67k stars 100 forks source link

Make greenlet working with a pool of Promises #43

Open empav opened 5 years ago

empav commented 5 years ago

Hi guys, maybe I'm wrong and need to give it a better look at service workers but what I'm trying to accomplish is the following:

1- I'd like to pass to greenlet an array of promises like the Promise.all(promises) return. 2- Await for them inside the greenlet function. 3- returning the result to the main app.

This is my code:

          try {
            const promises = validationAuto(chunk, workarea, criteria, test_groups); 
            if (window.Worker) {
              validationAutoWorkerized(promises);
            } else {
              await promises;
            }
          } catch (error) {
            console.log(error);
          }
const validationAuto = (chunk, workarea, criteria, test_groups) => {
  const validationPromises = chunk.map(id => {
    return new Promise((resolve, reject) => {
      postWorkareaValidationAuto(workarea, id, criteria, test_groups)
        .then(response => resolve(response))
        .catch(error => reject(error));
    });
  });
  return Promise.all(validationPromises);
};
const validationAutoWorkerized = greenlet(async promises => {
  const data = await promises;
  console.log(data);
  return data;
});

Any tip to accomplish it with greenlet? Thanks.

developit commented 4 years ago

Hi @epavan - you can't pass Promises to greenlet, because the code that generates the work those promises represent would still just be running on the main thread.

It's likely you're looking for something more like workerize-loader, which lets you import a module as a Worker:

// validation-auto.js
async function validationAuto(chunk, workarea, criteria, test_groups) {
  let validate;
  if (window.Worker) {
    // this special import runs the module and its dependencies in a worker:
    validate = (await import('workerize-loader!./validation-worker')).validate;
  }
  else {
    // if there's no Workers support, we'll just run it all on the main thread:
    validate = (await import('./validation-worker')).validate;
  }
  return validate(chunk, workarea, criteria, test_groups);
}
// validation-worker.js
export function validate(chunk, workarea, criteria, test_groups) {
  const validationPromises = chunk.map(id => {
    return new Promise((resolve, reject) => {
      postWorkareaValidationAuto(workarea, id, criteria, test_groups)
        .then(response => resolve(response))
        .catch(error => reject(error));
    });
  });
  return Promise.all(validationPromises);
}

The key with the above is that the code to create the Promises is itself moved into a Worker.

Purecaesar commented 4 years ago

@epavan if i understand your problem right. You can use it just like that, because if u are gonna make promisess you have to make it inside the worker.


const validationAutoWorkerized = greenlet(async (chunk, workarea, criteria, test_groups) => {
 const validationPromises = chunk.map(id => {
    return new Promise((resolve, reject) => {
      postWorkareaValidationAuto(workarea, id, criteria, test_groups)
        .then(response => resolve(response))
        .catch(error => reject(error));
    });
  });

  const data = await Promise.all(validationPromises);
  console.log(data);
  return data;
});

validationAutoWorkerized(chunk, workarea, criteria, test_groups);