这是承诺中错误处理的正确用法吗?

时间:2017-06-29 08:03:18

标签: javascript error-handling promise

我很难理解处理错误的最佳方法。 下面的代码是一个好的做法吗?

是否有更好,更短,更易于阅读的方式来处理流量和错误?

您如何编码处理所有错误,以免被吞下?谢谢。

  privateProperties.setSearchedData = function (data, searchFor) {
    return new Promise(function (resolve, reject) {
      switch (searchFor) {
        case "photos":
          try {
            var photoItems = [];

            if (data.items && data.items.constructor === Array) {
              data.items.forEach(function (value) {
                if (value.link) {
                  photoItems.push(value.link);
                } else {
                  console.error('Link is undefined');
                  reject(new Error('Link is undefined'));
                }
              });
              privateProperties._uiInstances['main'].uiReference.set("photos.photoItems",photoItems)
                .then(resolve(photoItems))
                .catch(function (error) {
                  reject(error);
                })
            } else {
              reject(new Error('Data.items is undefined or not array'));
            }
          } catch (e) {
            throw e;
          }
        break;

        case "videos":
        break
      }
    });

  };

3 个答案:

答案 0 :(得分:1)

如果我理解你的代码,你可以写:

privateProperties.setSearchedData = function(data, searchFor) {
  switch (searchFor) {

    case "photos":
      if (!Array.isArray(data.items)) 
        return Promise.reject("data.items is undefined or not an array");

      const photoItems = data.items.map(item => item.link);

      if (photoItems.some(item => !item)) {
        console.error('Link is undefined');
        return Promise.reject("Link is undefined");
     }

      return privateProperties._uiInstances['main'].uiReference
        .set("photos.photoItems", photoItems);

    case "videos":
      return Promise.reject("videos not supported");
  }
}

您实际上是在尝试返回uiReference.set承诺,所以请将其返回。没有必要catch拒绝它 - 拒绝将被传递给消费者处理。没有必要创建自己的承诺,然后根据其结果费力resolvereject您自己的新承诺。只需返回您想要的承诺。错误检查可以预先完成,并且在这种情况下会返回明确拒绝的承诺。

使用await,可能如下所示。您可以throw而不是返回Promise.rejectthrow将导致函数返回被拒绝的承诺,并将其作为理由。

privateProperties.setSearchedData = async function(data, searchFor) {
  switch (searchFor) {
    case "photos":
      return privateProperties._uiInstances['main'].uiReference
        .set("photos.photoItems", data.items.map(item => item.link));

    case "videos":
      throw new Error("videos not supported");
  }
}

我省略了对数组的检查,因为非数组将导致.map失败,这将导致整个函数返回由于某些原因拒绝的承诺,例如&#34 ;无法读取null"的属性map

我还假设重新设计uiReference.set来检查丢失或无效的链接,如果发生这种情况则拒绝,所以我们不必检查链接是否全部都在那里无论是。完成所有操作后,此功能实际上只需要打开searchFor,从数据项中提取链接,然后调用并返回uiReference.set。就个人而言,我更喜欢使用单独的功能来搜索照片和视频,在这种情况下,它变得非常干净:

privateProperties.setSearchedPhotosData = async function(data) {
  return privateProperties._uiInstances['main'].uiReference
    .set("photos.photoItems", data.items.map(item => item.link));
}

async的唯一剩余目的是将map(当data.items不是数组时)的失败转变为被拒绝的承诺。但是,如果这种情况代表编码错误,而不是您想要处理的半预期情况,那么最好让它抛出(通过删除async)。

答案 1 :(得分:0)

不,不是。 ;)使用不带new Error的拒绝,当您发现错误时,请不要使用throwreject( e )

然后你可以说

privateProperties.setSearchedData( ... )
  .then( callback )
  .catch( errorCallback );

旁注:将代码拆分为更多功能,以提高可读性。我想case "photos":内的所有内容(除了中断)都可以是它自己的函数。

答案 2 :(得分:0)

  1. 你捕获所有错误,但然后扔掉它们。它完全等于首先不抓住它们。使用reject代替throw

  2. 关于使用Promises的更简单,更易读的方法,您可以使用async await使您的代码更具可读性和简洁性,并在引擎盖下使用Promise。然后你的功能将是这样的:

    privateProperties.setSearchedData = async function(data,searchFor){

    switch (searchFor) {
        case "photos":
            var photoItems = [];
    
            if (data.items && data.items.constructor === Array) {
                data.items.forEach(function (value) {
                    if (value.link) {
                        photoItems.push(value.link);
                    } else {
                        console.error('Link is undefined');
                        throw new Error('Link is undefined');
                    }
                });
                privateProperties._uiInstances['main'].uiReference.set("photos.photoItems",photoItems);
                return photoItems;
            } else {
                throw new Error('Data.items is undefined or not array');
            }
            break;
    
        case "videos":
            break
    }
    

    };