【问题标题】:How to chain nested promises containing then and catch blocks?如何链接包含 then 和 catch 块的嵌套承诺?
【发布时间】:2019-10-07 22:27:25
【问题描述】:

如何链接ES6 嵌套Promises 与每个Promise 在嵌套有thencatch 块?

例如,考虑到每个 API 调用都返回一个 @ 987654332@?

$.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');
            }
         })
    }})

【问题讨论】:

    标签: javascript ecmascript-6 promise es6-promise


    【解决方案1】:

    如果你想链接 Promise,你可以让每个处理程序返回一个 Promise,然后从那里链接 thencatch 函数。我相信这表明了你想要做什么:

    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');
      });

    但是,重要的是要意识到这是一个没有分支逻辑的链。使用结构handle success -> handle error -> handle success,一旦你的错误处理程序返回有效的承诺,链的其余部分就无法判断之前发生的事情是成功处理程序还是错误处理程序的结果。这里没有分支逻辑,你需要嵌套 promise 来实现。

    这里有两个主要的选择。首先,您可以抛出不同的错误类型并在单个 catch 处理程序中处理每个不同的错误。其次,您可以改用async/await 语法。任何一个都可能适合你,但我认为他们需要一个单独的问题。

    【讨论】:

    • 这里最后一个 catch 块是所有前面的 then 块共有的,我猜。但这不是我需要的。我需要嵌套中的每个 Promise 都有自己的个体然后捕获块对。在这里,我认为只有链接的块对应于它们的 Promise 而不是 catch 块。如果我们对嵌套中的每个 Promise 有不同的错误处理,则拥有单独的 catch 块会有所帮助。
    • @AbhinandanKhilari 那么听起来好像您在描述固有嵌套的行为;也许如果你能举例说明描述这种链的语法是什么样的,那么我们也许可以用这种方法来实现这一点
    • 请参考问题中提到的sn-p。我在成功和错误回调中记录了消息,以确定哪个 API 调用成功或失败。我想知道如何通过 Promises 实现相同的目标。并且例如链接语法,您可以参考您发布的sn-p。在那里,我需要每个 then 阻止自己的 catch 块,以便可以准确识别链中哪个 Promise 被拒绝。例如,我想会有相同数量的 catch 块和 then 块的日志一样,'第一个错误','第二个错误',......只需要知道如何链接它们。
    • 我已经看到了 sn-p,但除了说“你在 then/catch 语句中放置了返回承诺的新 api 调用”之外,没有什么可说的了。如果不将后续调用放在then/catch 语句中,您就不能拥有像上面示例那样具有分支逻辑的承诺链
    • 这意味着如果我们必须在 then 中放入 API 调用并捕获块,那么结构将像一个回调地狱。与 Promise 的本质完全相反,因为 Promise 用于避免回调函数结构引起的回调地狱,对吧?
    【解决方案2】:

    你试过.done.fail吗?

    你可以重写代码如下

    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>

    【讨论】:

    • 其实我正在寻找 ES6 实现 Promises 的解决方案
    【解决方案3】:

    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
    })
    

    【讨论】:

    • 但是这里最后一个 then 和 catch 块丢失了它们所属的 Promise 的上下文。如果我们对嵌套中的每个 Promise 的 resolve 和 reject 有不同的实现,因此需要为每个 Promise 拥有一对独占的 then 和 catch 块怎么办?
    猜你喜欢
    • 2021-10-17
    • 2016-01-21
    • 1970-01-01
    • 2019-01-08
    • 2021-02-07
    • 2017-06-15
    • 2019-05-10
    • 2020-04-01
    • 1970-01-01
    相关资源
    最近更新 更多