Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/426.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 返回错误和抛出错误之间的差异_Javascript_Error Handling_Promise_Return - Fatal编程技术网

Javascript 返回错误和抛出错误之间的差异

Javascript 返回错误和抛出错误之间的差异,javascript,error-handling,promise,return,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

我在一个项目中发现了我不理解的以下代码:

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);
      });
  }
为什么
返回新错误('没有要获取的密钥!')
而不是
抛出新错误('没有要获取的密钥!')


另外,为什么不在
catch
块中抛出一个错误?

当您设计一个函数接口,并且有错误需要处理时,您可以选择如何返回错误。如果函数是同步的,那么您可以返回一些指示错误且易于与实际结果区分的sentinel值(Javascript中通常为
null
),或者
抛出一个异常,或者返回一个具有指示操作成功或失败的属性的对象

当您使用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);
  });
正在使用值或
错误
对象解析返回的承诺。这通常不是promise代码的编写方式,因为它需要调用方测试解析值的类型,以确定是否存在错误,这不是使用promise的简单、直接的方法。所以,对于你的问题,你通常会这样做:

return dbstore.getItem(key).catch(function(err) {
    throw new Error('The key (' + key + ") isn't accessible: " + err);
});
在这个函数中还有其他迹象表明它只是一个糟糕的代码

  • .then(函数(值){returnvalue;})
    是完全多余和不必要的。它毫无价值可言。
    已经是承诺的解析值。不用再申报了

  • 函数有时返回承诺,有时抛出同步异常。
    这是一个更痛苦的使用。如果查看第一个
    If(!key){
    语句,它返回一个错误对象,因为没有提供
    key
    参数。这意味着要使用此函数,必须捕获同步异常,请提供
    .then()
    .catch()
    处理程序并检查已解析承诺的类型,看看它是否恰好是一个错误对象。使用此函数是一个噩梦。这是一个糟糕的代码

  • 要按原样使用函数,调用方可能必须执行以下操作:

    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
    });
    
    将调用方的简单性与上面的混乱进行比较

    此实现具有以下一致性:

  • 它总是返回一个承诺。如果未提供
    ,它将返回一个被拒绝的承诺
  • 所有的错误都来自被拒绝的承诺
  • 承诺解决的价值始终是实际的成功价值
  • 没有一个
    .then()
    处理程序没有任何有用的功能

  • 返回错误是一件非常不寻常的事情,这不是它们的用途。这取决于您希望控制的位置。
    抛出
    立即将控制权交还给调用者:请参阅MDN:“和控制权将传递给调用堆栈中的第一个catch块。如果调用方函数中不存在catch块,程序将终止。”,而如果
    返回一个新错误,则必须以不同的方式处理它,在另一个位置可能该代码的作者认为try/catch对性能影响“太大”“对于代码-参见作者还添加了一个不必要的
    。然后
    ,他似乎不那么精通。。。