返回错误和抛出错误之间的区别

时间:2019-07-05 23:39:08

标签: javascript error-handling promise return

我在一个项目中发现了以下代码,我不明白。

get(key, store = null) {
    if (!key) {
      return new Error('There is no key to get!');
    }

    let dbstore = this.localforage;

    if (store !== null) {
      dbstore = store;
    }

    return dbstore
      .getItem(key)
      .then(function(value) {
        return value;
      })
      .catch(function(err) {
        return new Error('The key (' + key + ") isn't accessible: " + err);
      });
  }

为什么用return new Error('There is no key to get!');代替throw new Error('There is no key to get!');

还为什么不在catch块中引发错误?

1 个答案:

答案 0 :(得分:2)

设计功能接口时,如果要处理错误,则可以选择如何返回错误。如果该函数是同步的,则可以返回一些指示错误且易于与实际结果区分开的哨兵值(在Javascript中通常为null),也可以throw异常,也可以返回一个具有指示操作成功或失败的属性的对象。

当您使用带有promise接口的异步操作时,通常会拒绝带有Promise对象的Error作为表示错误的拒绝原因。这就是承诺的核心设计理论。成功通过可选的值来解决,错误会由于原因而拒绝。

这段代码:

return dbstore
  .getItem(key)
  .then(function(value) {
    return value;
  })
  .catch(function(err) {
    return new Error('The key (' + key + ") isn't accessible: " + err);
  });

使用值或Error对象解析返回的promise。通常,这不是编写承诺代码的方式,因为它将要求调用方测试解析值的类型,以判断是否存在错误,这不是使用承诺的简单明了的方法。因此,对于您的问题,您通常会这样做:

return dbstore.getItem(key).catch(function(err) {
    throw new Error('The key (' + key + ") isn't accessible: " + err);
});

此功能还有其他迹象,那就是错误的代码。

  1. .then(function(value) {return value;})完全多余且不必要。它根本没有增加任何价值。 value已经是承诺的已解决价值。无需再次声明。

  2. 该函数有时会返回一个promise,有时会引发一个同步异常。
    这甚至使使用起来更加痛苦。如果查看第一个if (!key) {语句,它将返回一个Error对象,因为未提供key参数。这意味着要使用此功能,您必须捕获同步异常,提供.then().catch()处理程序,并检查已解析的promise的类型,以查看它是否恰好是一个错误对象。使用此功能是一场噩梦。这是错误的代码。

要按原样使用该函数,调用者可能必须这样做:

let retVal = someObj.get(aKey);
if (typeof retVal === Error) {
    // got some synchronous error
} else {
    retVal.then(val => {
        if (typeof val === Error) {
            // got some asynchronous error
        } else {
            // got an actual successful value here
        }
    }).catch(err => {
        // got some asynchronous error
    })
}

函数实现可能是这样的:

get(key, store = null) {
    if (!key) {
        return Promise.reject(new Error('There is no key to get!'));
    }

    let dbstore = store || this.localforage;

    return dbstore.getItem(key).catch(function(err) {
        throw new Error('The key (' + key + ") isn't accessible: " + err);
    });
}

然后可以这样使用:

someObj.get(aKey).then(val => {
    // got some successful value here
}).catch(err => {
    // got some error here
});

将调用者的简单性与上面的混乱进行比较。

此实现具有以下一致性:

  1. 它总是返回承诺。如果未提供key,则返回拒绝的诺言。
  2. 所有错误均来自被拒绝的承诺
  3. 承诺实现的价值始终是实际的成功价值
  4. 没有.then()处理程序没有任何用处。