一般来说,您可以认为拒绝类似于同步throw
,而履行类似于同步return
。每当功能以某种方式不成功时,您都应该拒绝。这可能是超时、网络错误、输入错误等。
拒绝承诺,就像抛出异常一样,对控制流很有用。它不必代表真正的意外错误;它可以代表您完全预期和处理的问题:
function getProfile(email) {
return getProfileOverNetwork(email)
.then(null, function (err) {
//something went wrong getting the profile
if (err.code === 'NonExistantUser') {
return defaultUser;
} else if (profileCached(email)) {
return getProfileFromCache(email);//fall back to cached profile
} else {
throw err;//sometimes we don't have a nice way of handling it
}
})
}
拒绝让我们跳过正常的成功行为,直到我们找到一个知道如何处理它的方法。作为另一个例子,我们可能有一些深深嵌套在应用程序堆栈底部的函数,它会拒绝。这可能要到堆栈的最顶端才能处理,我们可以在其中记录它。关键是拒绝像同步代码中的异常一样沿堆栈向上传播。
一般来说,只要有可能,如果您正在努力编写一些异步代码,您应该考虑“如果这是同步的,我会写什么”。从那个到承诺的等价物通常是一个相当简单的转换。
在方法中可以使用被拒绝的 Promise 的一个很好的例子exists
:
function exists(filePath) {
return stat(filePath) //where stat gets last updated time etc. of the file
.then(function () { return true; }, function () { return false; })
}
请注意,在这种情况下,拒绝完全是意料之中的,只是意味着文件不存在。还要注意它是如何与同步函数并行的:
function existsSync(filePath) {
try {
statSync(filePath);
return true;
} catch (ex) {
return false;
}
}
你的例子
回到你的例子:
findUserByEmail
如果没有找到用户,我通常会选择拒绝承诺。这是您完全期望有时会发生的事情,但它是规范的例外,并且应该与所有其他错误非常相似地处理。同样,如果我正在编写一个同步函数,我也会有throw
一个例外。
有时只返回可能有用null
,但这取决于您的应用程序逻辑,可能不是最好的方法。