Search code examples
javascriptasync-awaitbabeljses6-promise

Can multiple callers subscribe to the same async function, using the Babel await keyword?


Multiple callers can subscribe to a function in progress if it returns a CommonJS promise:

let curWaitTask;
let lastWaitTime = new Date(1970, 0, 1);
let func1 = function() {
  if(curWaitTask) {
    return curWaitTask;
  }
  if((new Date() - lastWaitTime) > TWENTY_MINUTES) {
    lastWaitTime = new Date();
    curWaitTask = func2().then(func3).then(func4);
    return curWaitTask;
  }
}

Above is an expiring cache approach. The first call to func1 that happens after the twenty minute cache expires will cause the service to perform another async operation to update the cache. In the meantime, other calls to func1 may occur, which will await the same cache update operation instead of it happening again and again until the cache gets set (multiple times in a row, due to the all the calls).

Is there some way to get this behavior while using the clarity offered by the Babel await keyword, instead of a string of unwieldy .then()'s? In practice, it is getting ugly.


Solution

  • Just wrap the "unwieldy then chain" in an async function and use await in there:

    let curWaitTask;
    let lastWaitTime = new Date(1970, 0, 1);
    function func1() {
      if (!curWaitTask && (new Date() - lastWaitTime) > TWENTY_MINUTES) {
        lastWaitTime = new Date();
        curWaitTask = doTask();
      }
      return curWaitTask;
    }
    async function doTask() {
      return func4(await func3(await func2()));
    }
    

    It is (fortunately?) not possible inside an async function to refer to the new promise that is created from the current invocation, so using async function func1 is not really sensible here.