-1

Is there anything out there already that do similar to the following.

/**
 * ex.
 * const ret = await asyncify(Math.max)(arg1, arg2);
 */
asyncify(func) {
  return async (...inputs) => {
    // wait for all inputs being resolved
    const inputsResolved = await Promise.all(inputs);
    return await func(...inputsResolved);
  };
}

/**
 * ex.
 * const ret = await execute(Math.max, arg1, arg2);
 */
async execute(func, ...inputs) {
  // wait for all inputs being resolved
  const inputsResolved = await Promise.all(inputs);
  return await func(...inputsResolved);
}

With these functions (one or the other) I can then do something asynchronous without complex code structure to make sure the tasks are executed in correct sequence and maximally in parallel.

// Task A and B can run in parallel
const retA = asyncTaskA(payloadA);
const retB = asyncTaskB(payloadB);

// Task C and D depend on A and B, but they can run in parallel as well.
const retC = asyncify(
  (payloadC1, payloadC2) => {
    asyncTaskC(payloadC1.someField, payloadC2.otherField);
  }
)(retA, retB);
const retD = asyncify(asyncTaskD)(retA, retB);
// Task A and B can run in parallel
const retA = asyncTaskA(payloadA);
const retB = asyncTaskB(payloadB);

// Task C and D depend on A and B, but they can run in parallel as well.
const retC = execute(
  (payloadC1, payloadC2) => {
    asyncTaskC(payloadC1.someField, payloadC2.otherField);
  },
  retA,
  retB
);
const retD = execute(asyncTaskD, retA, retB);

If not, is it something that worth adding to the Promise similar to Promise.all?

const retC = Promise.asyncify(asyncTaskD)(retA, retB));

Update: adding a more complex example:

/**
 * A -> B
 * B -> C
 * A -> D
 * B,D -> E
 * C,E -> F
 */
async function aComplexWorkflow() {
  const A = Lib.execute(asyncTaskA);
  const B = Lib.execute(asyncTaskB, A);
  const C = Lib.execute(asyncTaskC, B);
  const D = Lib.execute(asyncTaskD, A);
  const E = Lib.execute(asyncTaskE, B, D);
  const F = Lib.execute(asyncTaskF, C, E);
  return F;
}

1 Answers1

1

Is there anything out there already that do similar to the following.

No.

I can then do something asynchronous without complex code structure

I don't think your code is any less complex than just writing

const [retA, retB] = await Promise.all([
  asyncTaskA(payloadA),
  asyncTaskB(payloadB),
]);

const retC = asyncTaskC(retA, retB);
const retD = asyncTaskD(id, forecast.result);

I'd even argue that using execute/asyncify makes it harder to understand than just inlining those.

Is it something that is worth adding to the Promise similar to Promise.all?

No - and please don't modify builtins!

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • I think the example I put there is not complex so that you could just await on retA and retB. But what if there is something more complicated. ``` A -> B; B -> C; A -> D; (B ,D) -> E; (C, E) -> F; ``` – Sampson Gao Sep 22 '22 at 00:52
  • In that case I'd recommend spelling it out with `.then` calls inside the function that does the parallel execution, not by putting an implicit `asyncify` on the involved functions. `const b = getB(a); return Promise.all([b.then(getC), Promise.all([b, getD(a)]).then(getE)]).then(getF);`. Sure, you could use a helper function like `execute` if you needed to spread the arguments, but I don't think it gets much easier to understand - and tbh although I worked a lot with promises, such intricate dependency networks rarely come up. – Bergi Sep 22 '22 at 01:08
  • Well, I agree that most of the workflows are not be complicated like that. I think libraries and utils are valuable for enabling us to write the more complicated use cases in simpler ways. – Sampson Gao Sep 22 '22 at 01:26