javascript - 返回错误和抛出错误的区别

标签 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 中抛出错误?堵塞?

最佳答案

当你设计一个函数接口(interface)并且有错误需要处理时,你就有了如何返回错误的设计选择。如果函数是同步的,您可以返回一些指示错误并且很容易与实际结果区分开来的标记值(在 Javascript 中通常为 null),或者您可以 throw一个异常,或者您可以返回一个对象,该对象具有指示操作成功或失败的属性。

当您使用 promise 接口(interface)进行异步操作时,通常会拒绝 PromiseError对象作为表示错误的拒绝原因。这就是 Promise 的核心设计理论。成功以可选值解决,错误以原因拒绝。

这段代码:

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

正在使用值或 Error 解决返回的 promise 目的。这通常不是 promise 代码的编写方式,因为它需要调用者测试解析值的类型以确定是否存在错误,这不是使用 promise 的简单、直接的方法。因此,对于您的问题,您通常会这样做:
return dbstore.getItem(key).catch(function(err) {
    throw new Error('The key (' + key + ") isn't accessible: " + err);
});

此函数还有其他迹象,表明它只是糟糕的代码。
  • .then(function(value) {return value;})完全是多余和不必要的。它根本没有增加任何值(value)。 value已经是 promise 的已解决值。无需再次声明。
  • 该函数有时会返回一个 promise ,有时会抛出一个同步异常。
    这甚至是一个进一步的使用痛苦。如果你看第一个if (!key) {语句,它返回一个错误对象是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
    });
    

    将这里调用者的简单性与上面的困惑进行比较。

    此实现具有以下一致性:
  • 它总是返回一个 promise 。如果 key没有提供,它返回一个被拒绝的 promise 。
  • 所有错误都来自被拒绝的 promise
  • promise 解决的值始终是实际成功值
  • 没有.then()无用的处理程序。
  • 关于javascript - 返回错误和抛出错误的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56910169/

    相关文章:

    php - Apache : .htaccess ErrorDocument up one level?

    promise - ECMAScript 6 链接 Promise

    javascript - NodeJS - 递归函数中的异步结果求和

    angular - Firebase 云函数以状态码 304 结束

    javascript - HTML : Page load every 5 secs and display countdown like 5, 4,3,2,1 然后重新加载页面

    javascript - 使用 jQuery floatThead 插件调整 jQuery UI 的大小

    javascript - React 看到除数组之外的所有内容

    c# - 如果URL不包含现有 Controller ,则404永远不会达到Application_Error

    javascript - CSS 模块不适用于 React 版本 16.6.0

    python - "takes 1 positional argument but 2 were given"同时找到函数的最小值