问题
How to chain ES6
nested Promises
with each Promise
in the nesting having then
and catch
blocks?
For example, what will be the Promise
then
and catch
blocks chaining implementation equivalent for following nested AJAX
calls implementation handled by success
and error
callbacks, considering every API call returns a Promise
?
$.ajax({
url: 'url1',
success: function() {
console.log('URL1 call success');
$.ajax({
url: 'url2',
success: function() {
console.log('URL2 call success');
},
error:function() {
console.log('URL2 call error');
}
})
},
error: function() {
console.log('URL1 call error');
$.ajax({
url: 'url3',
success: function() {
console.log('URL3 call success');
},
error:function() {
console.log('URL3 call error');
}
})
}})
回答1:
If you want to chain promises, you can have each handler return a promise, and then chain the then
and catch
functions from there. I believe this demonstrates what you're looking to do:
const getPromise = (time, reject=false) => new Promise((res, rej) => {
setTimeout(() => reject ? rej() : res('done'), time);
});
getPromise(500)
.then(() => {
console.log('first response');
return getPromise(500, false);
})
.then(() => {
console.log('second response');
return getPromise(500, true);
})
.catch((error) => {
console.log('you can have catch statements return promises, too');
return getPromise(700, true)
})
.then(() => {
// this structure falls down here; is this a response to the promise returned from
// the catch, or the promise returned from the 'second response' part?
console.log('third response');
})
.catch(() => {
console.error('hit an error');
});
However, it's important to realise that this is a chain with no branching logic. With the structure handle success
-> handle error
-> handle success
, once your error handlers return valid promises, the remainder of the chain cannot tell whether what came before was a result of the success or error handlers. There's no branching logic here and you need nesting of promises to achieve that.
There are two main alternatives here. First you could throw different error types and handle each different error in a single catch
handler. Second, you could use async
/await
syntax instead. Either may work for you but I think that they'd warrant a separate question.
回答2:
This can be written like this :
function makeAjaxCall(url){
return new Promise((s, f) => {
$.ajax({
url: url,
success: s,
error: f
})
})
}
makeAjaxCall('url1')
.then((data) => {
console.log('URL1 call success');
return makeAjaxCall('url2')
}, (error) => {
console.log('URL1 call error');
return makeAjaxCall('url3')
})
.then(() => {
//It Could be Either url2 success or url3 success
}, () => {
//It Could be Either url2 failure or url3 falure
})
回答3:
have you tried .done
and .fail
?
You can re-write the code as below
const doAjaxCall = (url) => $.ajax({ url })
const callURL = (url) => doAjaxCall(url)
.done(() => console.log(`${url} is ok!`) )
.fail(() => console.log(`${url} failed!`) );
doAjaxCall('/url1')
.done(() => {
console.log('url1 is ok!');
callURL('/url2');
})
.fail(callURL('url3'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
来源:https://stackoverflow.com/questions/56239772/how-to-chain-nested-promises-containing-then-and-catch-blocks