简体   繁体   中英

Fix a nested promise chain

I have an existing Promise chain that makes me very uncomfortable. I don't like nested callbacks, let alone nested promise chains. I have refactored it, but curious if it can be done better.

The reason for the refactor is that I need to add an additional functional call to this flow, right in the middle 😎

EXISTING:

initFirestore()
  .then(() => {
    console.log('Firestore has been initialized.');
    seedServices()
      .then(customerId => {
// here is where my new function would need to live.
        seedFirestore()
          .then(() => {
            console.log('Seed created for Customer: ', customerId);
          })
          .catch(err => {
            console.log('Trouble seeding firestore with seedTemplates', err);
          });
      })
      .catch(customerId => {
        console.log('Seed created with warnings for  Customer: ', customerId);
      });
  })
  .catch(err => {
    throw new Error(err);
  });

My Proposed update:

initFirestore()
  .then(() => {
    console.log('Firestore has been initialized.');
  })
  .catch(err => {
    throw new Error(err);
  })
  .then(() => seedServices())
  .then(customerId => customerId)
  .catch(err => {
    console.log('Trouble seeding firestore with seedTemplates', err);
  })
  .then(async customerId => {
    await myNewFunction().then(
      (response) => {
        console.log(response);
      }
    );
    return customerId;
  })
  .then(async customerId => {
    await seedFirestore();
    return customerId;
  })
  .then(customerId => {
    console.log('Seed created for Customer: ', customerId);
  })
  .catch(customerId => {
    console.log('Seed created with warnings for  Customer: ', customerId);
  });

I'm not happy with the mixing of catch in the chain...How else could I do this?

Actually what you are doing is ok, if you mean to catch errors, log a warning and then continue anyway.

This is the async/await equivalent:

let customerId;
try {

    try {
      await initFirestore()
      console.log('Firestore has been initialized.');
    } catch(err) {
      throw new Error(err);
    });

    try {
      customerId = await seedServices());
    } catch(err) {
      console.log('Trouble seeding firestore with seedTemplates', err);
    };

    const response = await myNewFunction();
    console.log(response);

    await seedFirestore();
    console.log('Seed created for Customer: ', customerId);

} catch (err) {
   console.log('Seed created with warnings for  Customer: ', customerId);
}

What's strange here is:

  1. Immediately re-throwing the error you got, wrapped in a new Error() .
  2. Using exceptions for warnings

And, you can probably clean up your code a bit by lifting the customerId variable outside the first then, so you don't have pass it around everywhere.

Edit there are problems with your code, not every path will correctly forward customerId to the next then() handler. If you want to use then()/catch() instead of async/await.

One question I would have is, do you really want to continue the operation even after seedServices fails. My guess is 'no', so that would cause me to rewrite your code to:

let customerId;

initFirestore()
  .then(() => {
    console.log('Firestore has been initialized.');
    return seedServices();
  })
  .then(cId => {
    customerId = cId;
    return myNewFunction();
  })
  .then(() => seedFireStore());
  .then(() => {
    console.log('Seed created for Customer: ', customerId);
  })
  .catch(customerId => {
    console.log('Error while creating seed for customer ', customerId);
  });

async/await equivalent:

let customerId;

try {
  await initFirestore()
  const customerId = await seedServices();
  await myNewFunction();
  await seedFireStore());

  console.log('Seed created for Customer: ', customerId);

} catch(err) {
  console.log('Error while creating seed for customer ', customerId);
});

If you did mean to catch errors and continue anyway (after seedServices), my recommendation would be to split your operations in a few different functions. This is always nicer than nesting your promise chains.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM