How to chain nested promises containing then and catch blocks?

℡╲_俬逩灬. 提交于 2021-01-29 09:48:43

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!