Search code examples
javascriptasynchronouspromise

Migrating from then/catch promises chain to async/await


I'm trying to convert a chain of promises .then().catch to async/await functions

const chain = [
    {
        onFulfilled: () => {/*some logic*/},
        onRejected: () => {/*some logic*/},
    {
        onFulfilled: () => {/*some logic*/},
        onRejected: () => {/*some logic*/},
    {
        onFulfilled: () => {/*some logic*/},
        onRejected: () => {/*some logic*/},
    },
    //...
];
const data = 'initial data';
let promise = Promise.resolve(data);
let i = 0;
while (i < chain.length) {
    promise = promise.then(chain[i].onFulfilled).catch(chain[i].onRejected);
    i++;
}

The final promise is equal to:

promise = Promise.resolve()
.then(chain[0].onFulfilled).catch(chain[0].onRejected)
.then(chain[1].onFulfilled).catch(chain[1].onRejected)
.then(chain[2].onFulfilled).catch(chain[2].onRejected)
....

Here is what I've tried so far

let data = 'initial data';
for (const fn of chain) {
  try {
      data = await fn.onFulfilled(data);
  } catch (e) {
      data = await fn.onRejected(e);
  }
}

The prolem is: if fn.onRejected throw an error, the error causes for loop to stop rather than handled by the next fn.onRejected


Solution

  • Here is the working code. Messy but works

    let data = 'initial data', unhandledError;
    
    for (const fn of chain) {
      if(unhandledError) {
        try {
          data = await fn.onRejected(unhandledError);
          unhandledError = null;
        } catch (e) {
          unhandledError = e;
        }
        continue;
      }
    
      try {
          data = await fn.onFulfilled(data);
          unhandledError = null;
      } catch (e) {
        try {
          data = await fn.onRejected(e);
          unhandledError = null;
        } catch (e) {
          unhandledError = e;
        }
      }
    
    if(unhandledError) throw unhandledError;