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
2 Answers
Reset to default 4This 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:
- return another promise
- return a synchronous value (or undefined)
- 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条)