我在项目中发现以下代码,我不明白:
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
块中抛出错误?
当你设计一个函数接口并且有错误需要处理时,你可以选择如何返回错误。如果函数是同步,您可以返回一些指示错误的哨兵值,并且很容易与实际结果区分开来(在Javascript中通常是
null
),或者您可以throw
异常,或者您可以返回一个对象具有指示操作成功或失败的属性。
当您使用 Promise 接口进行 异步 操作时,通常会拒绝
Promise
,并使用 Error
对象作为拒绝原因来表示错误。这就是 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
已经是承诺的解析值。无需再次声明。
该函数有时会返回一个 Promise,有时会抛出一个同步异常。
使用起来更加痛苦。如果您查看第一个
if (!key) {
语句,如果未提供 key
参数,它将返回一个 Error 对象。这意味着要使用此函数,您必须捕获同步异常,提供 .then()
和 .catch()
处理程序并检查已解析 Promise 的类型以查看它是否恰好是错误对象。这个功能用起来简直是一场噩梦。这是糟糕的代码。
要按原样使用该函数,调用者可能必须这样做:
let retVal = someObj.get(aKey);
if (retVal instanceof Error) {
// got some synchronous error
} else {
retVal.then(val => {
if (val instanceof 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
});
将这里调用者的简单性与上面的混乱进行比较。
此实现具有以下一致性:
key
,则返回拒绝的承诺。.then()
处理程序不做任何有用的事情。