promise-fun icon indicating copy to clipboard operation
promise-fun copied to clipboard

p-* version for promise-queue(max-concurrent=1, max-lenght=1)

Open LumaKernel opened this issue 4 years ago • 2 comments

It's useful for the situation like "queue some processing like building up to 1, and do not run at the same time".

naming candidates

I didn't came up with good name.

  • p-serial

implementation with promise-queue

import Queue from "promise-queue";

const pBlah1 = (promiseGetter) => {
  const maxConcurrent = 1;
  const maxQueue = 1;
  const queue = new Queue(maxConcurrent, maxQueue);
  return () => queue.add(promiseGetter).catch((e) => {if (e.message !== 'Queue limit reached') throw e;})
}

implementation from scratch

NOTE: this is fully written by me and publishing under public domain.

const pBlah2 = (promiseGetter) => {
  let waitProm = null;
  let waitResolve = null;
  let waitReject = null;
  let running = false;
  const done = () => {
    const waitResolveOld = waitResolve;
    const waitRejectOld = waitReject;
    running = false;
    waitProm = null;
    waitResolve = null;
    waitReject = null;
    if (waitResolveOld) {
      promiseGetter()
        .then((v) => {
          done();
          waitResolveOld(v);
        })
        .catch((e) => {
          done();
          waitRejectOld(e);
        });
    }
  };
  return () => {
    if (running) {
      if (!waitProm) {
        waitProm = new Promise((resolve, reject) => {
          waitResolve = resolve;
          waitReject = reject;
        });
      }
      return waitProm;
    }
    running = true;
    return promiseGetter()
      .then((v) => {
        done();
        return v;
      })
      .catch((e) => {
        done();
        throw e;
      });
  };
};

usage example

const wait = (ms) =>
  new Promise((resolve) => {
    setTimeout(resolve, ms);
  });

const a = async () => {
  await wait(2000);
  console.log("hi");
};

const f = pBlah1(a);
// const f = pBlah2(a);

(async () => {
  f(); // start immediately
  await wait(500);
  f(); // queued because running
  await wait(500);
  f(); // ignored because running and queue is full
})();

hi is only shown 2 times.

vs others

  • vs p-limit: this will run all queued promises.
  • vs p-debounce: this will run concurrently
  • vs p-queue: no option to limit max length
  • vs promise-queue: easy for the specific case

LumaKernel avatar Oct 16 '21 13:10 LumaKernel

vs p-limit: this will run all queued promises.

It could potentially receive an option to discard overflowing tasks instead of queuing them up.


vs p-queue: no option to limit max length

Regardless of the outcome here, I think it would be useful to add some ways to control the max count there.


And not mentioned https://github.com/sindresorhus/p-throttle could potentially receive a totalLimit option.

sindresorhus avatar Oct 17 '21 12:10 sindresorhus

All your ideas sound nice.

They may (and this issue's one can) accept args, but it is not clear the real run sequence is [1,2] vs [1,3] for f(1); await wait(500); f(2); await wait(500); f(3);; i.e. simply drop overflowed vs somehow prioritize ones come later.

LumaKernel avatar Oct 17 '21 13:10 LumaKernel