Can someone tell me why my promise queue don't work?

Advertisements

I’m trying to write a simple promise queue function, the function will process 50 tasks with 10 concurrent promises:

const sendTasks = () => {
  let tasks = 50;
  const concurrentCount = 10;
  let promisePool = 0;

  while (tasks > 0) {
    console.log(`current tasks: ${tasks}`);
    while (promisePool < concurrentCount && task > 0) {
      console.log("create promise");
      tasks--;
      promisePool++;
      const promise = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("haha");
        }, Math.floor(Math.random() * 3) * 1000);
      });

      promise.then((value) => {
        console.log(value);
        promisePool--;
      });

      console.log(`current promisePool: ${promisePool}`);
    }
  }  

  return "done";
};

But when I execute it, the promises seems never resolve, then keep stuck in the task>0 while loop. Can someone explain to me why the promises never resolve?

>Solution :

A while loop inside a synchronous function will never yield control flow to Promise .thens, or to anything else. You will need to restructure the code to wait for the promises to resolve without fully terminating the sendTasks function and also without blocking the engine.

One approach is to push each Promise to an array, then await a Promise.any on that array. Have the Promises remove themselves from the array when they’re finished, and recursively push more Promises to the array. Then return when no more Promises exist in the array.

const sendTasks = async () => {
  let tasks = 50;
  const concurrentCount = 10;
  let promisePool = 0;
  let promises = [];
  const enqueueNext = () => {
    if (!tasks) return;
    // creating this variable just for the sake of logging
    const thisTask = tasks--;
    console.log("create promise", thisTask);
    const prom = new Promise((resolve) => {
      setTimeout(() => {
        promises = promises.filter(p => p !== prom);
        console.log('resolving', thisTask);
        resolve("haha");
        // recursive asynchronous call; init the next promise, if there is one
        enqueueNext();
      }, Math.floor(Math.random() * 3) * 1000);
    });
    promises.push(prom);
  };
  for (let i = 0; i < concurrentCount; i++) {
    enqueueNext();
  }
  while (promises.length) {
    await Promise.any(promises);
  }
  console.log("done");
};
sendTasks();

Leave a ReplyCancel reply