javascript - Cleaner way to catch an error in a chain of nested promises? - Stack Overflow

I'm new to working with promises and am noticing that, in order to catch an error in a chain of ne

I'm new to working with promises and am noticing that, in order to catch an error in a chain of nested promises, I need to invoke the catch method on each promise in the chain. Is there a cleaner way to write this?

      poll.pollForCandidates().then((candidates) => {
        let clientId = candidates[0].clientId;
        poll.getUnprocessedCandidates({context, clientId, candidates})
          .then((unprocessedCandidates) => {
            console.log(unprocessedCandidates);
            poll.addCandidatesToQueue(context, unprocessedCandidates)
              .then((processedCandidates) => {
                console.log(processedCandidates);
                poll.addCandidatesToTable(processedCandidates)
                  .then((result) => {
                    console.log(result);
                  })
                  .catch((error) => {
                    console.log(error);
                  });
              })
              .catch((error) => {
                console.log(error); 
              })
          })
          .catch((error) => {
             console.log(error); 
          })
      })
      .catch(() => {
        console.done(error); 
      });
    };

I'm new to working with promises and am noticing that, in order to catch an error in a chain of nested promises, I need to invoke the catch method on each promise in the chain. Is there a cleaner way to write this?

      poll.pollForCandidates().then((candidates) => {
        let clientId = candidates[0].clientId;
        poll.getUnprocessedCandidates({context, clientId, candidates})
          .then((unprocessedCandidates) => {
            console.log(unprocessedCandidates);
            poll.addCandidatesToQueue(context, unprocessedCandidates)
              .then((processedCandidates) => {
                console.log(processedCandidates);
                poll.addCandidatesToTable(processedCandidates)
                  .then((result) => {
                    console.log(result);
                  })
                  .catch((error) => {
                    console.log(error);
                  });
              })
              .catch((error) => {
                console.log(error); 
              })
          })
          .catch((error) => {
             console.log(error); 
          })
      })
      .catch(() => {
        console.done(error); 
      });
    };
Share Improve this question edited Jul 10, 2017 at 4:43 tripleee 190k36 gold badges313 silver badges361 bronze badges asked Jul 10, 2017 at 3:27 Michael P.Michael P. 1,4133 gold badges14 silver badges34 bronze badges 4
  • 1 Oh no! I remember it is a very mon anti pattern. Return promises from .then. And the next .then handler will have the returned promise's resolved/reject value – bugwheels94 Commented Jul 10, 2017 at 3:28
  • I think that "async" library would be a better approach. Did you try async waterfall? – Daniel Vukasovich Commented Jul 10, 2017 at 3:47
  • Use await. But with your existing code, you can also remove all the .catch(error => console.done(error) calls except the last one. They do nothing. – user663031 Commented Jul 10, 2017 at 3:55
  • Nearly all those .catch() statements are wrong for several reasons. You should chain your statements and only put a .catch() in the places you actually need to handle the error. Plus, these .catch() statements that only log and don't return anything actually change the promises from rejected to fulfilled which is likely NOT what you want. – jfriend00 Commented Jul 10, 2017 at 3:58
Add a ment  | 

2 Answers 2

Reset to default 4

This is the shorter way to do it:

poll.pollForCandidates()
    .then((candidates) => poll.getUnprocessedCandidates({ context, candidates[0].clientId, candidates }))
    .then((unprocessedCandidates) => poll.addCandidatesToQueue(context, unprocessedCandidates))
    .then((processedCandidates) => poll.addCandidatesToTable(processedCandidates))
    .then(console.log)
    .catch(console.error);

Explanation:

This is called posing promises, and it's one of the great superpowers of promises. Each function will only be called when the previous promise has resolved, and it'll be called with that promise's output.

There are three things you can do inside the then function:

  1. return another promise
  2. return a synchronous value (or undefined)
  3. throw a synchronous error

Here in the example above, we return a promise, so we can use .then to continue the posing promises.

At the end, the console.log gets the result and call the console.log with it. (Same with the console.error)

That's it. Once you understand this trick, you understand promises.

You can continue reading about it here: We have a problem with promises - By: Nolan Lawson

Like @bugwheels94 mentioned, you can return your promises from within .then and add another .then outside of the previous .then. Also, .then can take 2 arguments - the second one is for catching errors. It's a bit difficult to explain in words so here's an example.

poll.pollForCandidates()
  .then((candidates) => {
    let clientId = candidates[0].clientId;

    return poll.getUnprocessedCandidates({context, clientId, candidates})
      .then((unprocessedCandidates) => {
        console.log(unprocessedCandidates);
        return poll.addCandidatesToQueue(context, unprocessedCandidates)
      }, (error) => {
         console.log(error); 
      })
      .then((processedCandidates) => {
        console.log(processedCandidates);
        return poll.addCandidatesToTable(processedCandidates)
      }, (error) => {
        console.log(error); 
      })
      .then((result) => {
        console.log(result);
      }), (error) => {
        console.log(error);
      });
  })
  .catch((error) => {
    console.log(error);
  });

Edit: @jfriend00 brought up a good about using all of those .catch methods. Here's what the code would look like with a single .catch at the end of the chain.

poll.pollForCandidates()
  .then((candidates) => {
    let clientId = candidates[0].clientId;

    return poll.getUnprocessedCandidates({context, clientId, candidates})
      .then((unprocessedCandidates) => {
        console.log(unprocessedCandidates);
        return poll.addCandidatesToQueue(context, unprocessedCandidates)
      })
      .then((processedCandidates) => {
        console.log(processedCandidates);
        return poll.addCandidatesToTable(processedCandidates)
      })
      .then((result) => {
        console.log(result);
      });
  })
  .catch((error) => {
    console.log(error);
  });

Edit 2: Removing those extra console.log statements allows you to make it even cleaner.

poll.pollForCandidates()
  .then((candidates) => {
    let clientId = candidates[0].clientId;

    return poll.getUnprocessedCandidates({context, clientId, candidates})
      .then(unprocessedCandidates => poll.addCandidatesToQueue(context, unprocessedCandidates))
      .then(poll.addCandidatesToTable)
      .then((result) => {
        console.log(result);
      });
  })
  .catch((error) => {
    console.log(error);
  });

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744356982a4570279.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信