代码之家  ›  专栏  ›  技术社区  ›  wallop

Javscript Promise:拒绝处理程序vs捕获[duplicate]

  •  1
  • wallop  · 技术社区  · 7 年前

    new Promise.then(resolveHandler).catch()
    

    而不是

    new Promise().then(resolveHandler, rejectHandler).catch()
    

    有什么特别的原因吗??

    new Promise().then(resolveHandler,rejectHandler).catch()
    

    更有用是因为

    1. 我可以使用rejectHandler来处理调用Promise.reject的设计/预期错误场景。

    有人知道为什么rejectHandler不常被使用吗?

    更新:我知道rejectHandler和catch是如何工作的。问题是,为什么我看到更多的人同时使用catch和rejectHandler?这是最佳做法还是有一些优势?

    原因不仅仅是因为reject中的错误是由catch处理的,主要是因为链接。当我们链接promise.then.then.then.then时,有一个resolve,reject模式证明链接起来有点棘手,因为您不想实现一个rejecthandler来将rejectData转发到链上。仅使用promise/then/catch和resolve/return/throw在链接N个表时非常有用。 @鲍勃·方格(公认的答案)也谈到了其中的一部分。

    getData(id) {
            return service.getData().then(dataList => {
                const data = dataList.find(data => {
                    return data.id === id;
                });
                if (!data) {
                    // If I use Promise.reject here and use a reject handler in the parent then the parent might just be using the handler to route the error upwards in the chain
                  //If I use Promise.reject here and parent doesn't use reject handler then it goes to catch which can be just achieved using throw.
                    throw {
                        code: 404,
                        message: 'Data not present for this ID'
                    };
                }
                return configuration;
            });
        }
    
    
    //somewhere up the chain
    ....getConfiguration()
                .then(() => {
                    //successful promise execution
                })
                .catch(err => {
                    if (err.code) {
                        // checked exception
                        send(err);
                    } else {
                        //unchecked exception
                        send({
                            code: 500,
                            message: `Internal Server error: ${err}`
                        });
                    }
                });
    

    使用这些我需要担心的就是承诺/然后/捕获以及解决/返回/抛出链中的任何位置。

    3 回复  |  直到 7 年前
        1
  •  5
  •   Bob Fanger    7 年前

    不同之处在于,如果resolveHandler中发生错误,则rejectHandler不会处理该错误,而是只处理原始承诺中的拒绝。

    rejectHandler没有和catch结合使用那么多,因为大多数时候我们只关心它 某物 出了问题。
    只创建一个errorhandler使代码更容易推理。

    catch().then().catch()

        2
  •  4
  •   sr9yar Ayushman Parchoria    6 年前

    两个都不比另一个有用。当抛出错误或拒绝承诺时,将同时调用被拒绝的处理程序和catch回调。

    希望以下内容能帮助解释我的意思:

    somePromise
      .then(
          function() { /* code when somePromise has resolved */ },
          function() { 
            /* code when somePromise has thrown or has been rejected. 
            An error thrown in the resolvedHandler 
            will NOT be handled by this callback */ }
       );
    
    somePromise
      .then(
          function() { /* code when somePromise has resolved */ }
       )
       .catch(
          function() { 
            /* code when somePromise has thrown or has been rejected OR 
            when whatever has occurred in the .then 
            chained to somePromise has thrown or 
            the promise returned from it has been rejected */ }
       );
    

    请注意,在第一个代码段中,如果解析的处理程序抛出,则不存在被拒绝的处理程序(或 catch .then

        3
  •  0
  •   Community Mohan Dere    6 年前

    正如帖子中所述,在同一个调用中提供一个resolve和reject处理程序 .then 允许与成功处理程序中抛出的错误分开处理前一个承诺的拒绝,或者从成功处理程序返回被拒绝的承诺。

    因为返回时没有抛出错误的拒绝处理程序会恢复承诺链的fufilled通道,所以如果前一个拒绝处理程序正常返回,则不会调用final catch处理程序。

    然后问题就转移到用例、开发成本和知识水平上。

    理论上,双参数形式 then 调用可用于重试操作。但由于硬编码的承诺链是静态设置的,因此重试操作并不简单。更简单的重试方法可能是使用 async await

    async function() {
        let retries = 3;
        let failureErr = null;
        while( retries--) {
           try {
              var result = await retryableOperationPromise() 
              return result;
           }
           catch( err) {
              failureErr = err;
           }
         }
         throw failureErr // no more retries
    }
    

    其他用例可能并不普遍。

    开发或商业决策的成本。

    如果告诉用户稍后重试是可以接受的,那么它可能比对拒绝承诺的具体原因做任何事情都要便宜。例如,如果我试图预订午夜以上的航班,当航空公司提高价格时,我通常会被告知“发生了错误,请稍后再试”,因为在预订开始时给我的价格将不被兑现。

    我怀疑promise的用法通常是基于实例,而不是对主题的深入了解。对于经验不足的开发人员(可能是成本问题),程序经理也可能希望使代码库尽可能简单。

    “最佳实践”可能并不真正适用于决定如何使用承诺,如果使用是有效的。一些开发人员和管理人员会从原则上避免某些形式的使用,但并不总是基于技术优点。