Promise objects can be in one of three states:
- Pending: This is the initial state, neither fulfilled nor rejected
- Fulfilled: This is the final state where it executed successfully and
produced a result - Rejected: This is the final state where execution failed
Consider this code segment similar to the one we'll use later in this chapter:
notes.read(req.query.key)
.then(note => { return filterNote(note); })
.then(note => { return swedishChefSpeak(note); })
.then(note => {
res.render('noteview', {
title: note ? note.title : "",
notekey: req.query.key,
note: note
});
})
.catch(err => { next(err); });
There are several places where errors can occur in this little bit of code. The notes.read function has several possible failure modes: the filterNote function might want to raise an alarm if it detects a cross-site scripting attack. The Swedish chef could be on strike. There could be a failure in res.render or the template being used. But we have only one way to catch and report errors. Are we missing something?
The Promise class automatically captures errors, sending them down the chain of operations attached to the Promise. If the Promise class has an error on its hands, it skips over the .then functions and will instead invoke the first .catch function it finds. In other words, using instances of Promise provides a higher assurance of capturing and reporting errors. With the older convention, error reporting was trickier, and it was easy to forget to add correct error handling.