Codementor Events

Expected errors and Promise.all

Published Jan 15, 2019

Promise.all is a great ES6 feature, which makes it remarkably easy to combine together multiple promises. Things, however, might get a little bit tricky, when not all the promises fed into Promise.all are expected to succeed.

Consider the case of design documents when starting up PouchDB. PouchDB supports promises and Promise.all would be a nice way to create those documents before the application starts:

import designDocs from './designDocs';

const db = new PouchDB(config.database);

export async function databaseSetup() {
  const designPromises = designDocs.map(designDoc => db.put(designDoc));

  await Promise.all(designPromises);
}

And this works for the first time, but not for next ones because PouchDB will throw an error if you try to create a new doc with the same _id as the existing one. What is even worse, there is no trivial way to solve this issue. Doing:

  await Promise.all(designPromises).catch((error) => {
    // handle it here
  });

Will only enable you handle the first error that occured during the Promise.all and you will have no way to handle other errors. Luckily there is way to handle those expected errors before Promise.all an let it deal with only genuine unexcpected error cases:

import designDocs from './designDocs';

const db = new PouchDB(config.database);

export async function databaseSetup() {
  const designPromises = designDocs.map(designDoc => db.put(designDoc).catch(async 
  (error) => {
    if (error.name !== 'conflict') throw error;

    const existingDesignDoc = await db.get(designDoc._id);
    return db.put({
      ...designDoc,
      _rev: existingDesignDoc._rev,
    });
  }));

  await Promise.all(designPromises);
}

By handling expected errors before Promise.all we are able to asynchronously create/update all the required design documents before starting the application.

Discover and read more posts from Kaarel Allemann
get started