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对性能影响“太大”“对于代码-参见作者还添加了一个不必要的。然后
,他似乎不那么精通。。。