I am thinking about when exactly I need to reject a promise. I found a couple of questions regarding this topic, but could not find a proper answer. When should I reject a promise?
我在想什么时候该拒绝一个承诺。我找到了几个关于这个话题的问题,但是找不到一个合适的答案。我什么时候应该拒绝一个承诺?
This article http://howtonode.org/6666a4b74d7434144cff717c828be2c3953d46e7/promises says:
这篇文章http://howtonode.org/6666a4b74d7434144cff717c828be2c3953d46e7/promises表示:
- Resolve: A successful Promise is 'resolved' which invokes the success listeners that are waiting and remembers the value that was resolved for future success listeners that are attached. Resolution correlates to a returned value.
- 解决方案:一个成功的承诺是“解决”的,它调用等待并记住为未来成功的侦听器所确定的价值。分辨率与返回值相关。
- Reject: When an error condition is encountered, a Promise is 'rejected' which invokes the error listeners that are waiting and remembers the value that was rejected for future error listeners that are attached. Rejection correlates to a thrown exception.
- 拒绝:当遇到错误条件时,一个承诺将被“拒绝”,该承诺将调用正在等待的错误侦听器并记住为附加的未来错误侦听器而被拒绝的值。拒绝与抛出的异常相关。
Is this the principle guideline? That one only reject a promise if an exception occured?
这是原则方针吗?只有在发生异常时才拒绝承诺?
But in case of a function like
但如果是像这样的函数。
findUserByEmail()
I'd would expect the function to return a user, so that I can continue the chain without verifying the result
我希望函数返回一个用户,这样我就可以在不验证结果的情况下继续执行链
findUserByEmail()
.then(sendWelcomeBackEmail)
.then(doSomeNiceStuff)
.then(etc..)
What are best / common practises?
最好的/常见的做法是什么?
2 个解决方案
#1
14
In general you can think of rejecting as being analogous to a synchronous throw
and fulfilling as being analogous to a synchronous return
. You should reject whenever the function is unsuccessful in some way. That could be a timeout, a network error, incorrect input etc. etc.
通常,您可以将拒绝视为类似于同步抛出,而实现则类似于同步返回。当函数以某种方式失败时,您应该拒绝。这可能是一个超时,一个网络错误,错误的输入等等。
Rejecting a promise, just like throwing an exception, is useful for control flow. It doesn't have to represent a truly unexpected error; it can represent a problem that you fully anticipate and handle:
拒绝一个承诺,就像抛出一个异常一样,对于控制流是有用的。它不一定代表一个真正意想不到的错误;它可以代表一个你完全预料和处理的问题:
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
}
})
}
The rejection lets us jump over the normal success behavior until we get to a method that knows how to handle it. As another example, we might have some function that's deeply nested at the bottom of the applications stack, which rejects. This might not be handled until the very top of the stack, where we could log it. The point is that rejections travel up the stack just like exceptions do in synchronous code.
拒绝让我们跳过正常的成功行为,直到我们找到一个知道如何处理它的方法。作为另一个例子,我们可能有一些深嵌在应用程序堆栈底部的函数,它会拒绝。直到堆栈的最顶端,我们才能对其进行日志记录。关键是拒绝在堆栈中传播,就像同步代码中的异常一样。
In general, wherever possible, if you are struggling to write some asynchronous code, you should think "what would I write if this were synchronous". It's usually a fairly simple transformation to get from that, to the promised equivalent. A nice example of where rejected promises might be used is in an
exists` method:
通常,只要可能,如果您正在努力编写一些异步代码,您应该考虑“如果这是同步的,我将编写什么”。它通常是一个相当简单的变换,从那个变换到承诺的等价变换。anexist的方法中有一个很好的例子说明拒绝的承诺可能被使用:
function exists(filePath) {
return stat(filePath) //where stat gets last updated time etc. of the file
.then(function () { return true; }, function () { return false; })
}
Notice how in this case, the rejection is totally expected and just means the file does not exist. Notice also how it parallels the synchronous function though:
注意,在这种情况下,拒绝是完全可以预期的,这意味着文件不存在。注意它是如何与同步函数平行的:
function existsSync(filePath) {
try {
statSync(filePath);
return true;
} catch (ex) {
return false;
}
}
Your Example
Returning to your example:
回到你的例子:
I would normally chose to reject the promise resulting from findUserByEmail
if no user was found. It's something you fully expect to happen sometimes, but it's the exception from the norm, and should probably be handled pretty similarly to all other errors. Similarly if I were writing a synchronous function I would have it throw
an exception.
如果没有找到用户,我通常会拒绝findUserByEmail的承诺。这是你在某些时候完全期望会发生的事情,但这是常规的例外,应该与所有其他错误处理相似。类似地,如果我在编写一个同步函数,我会让它抛出一个异常。
Sometimes it might be useful to just return null
instead, but this would depend on your applications logic and is probably not the best way to go.
有时只返回null可能有用,但这将取决于应用程序的逻辑,而且可能不是最好的方法。
#2
5
I know where you're coming from. Q and Q documentation can quite easily have you believe that deferred/promise rejection is all about exception handling.
我知道你来自哪里。Q和Q文档可以很容易地让您相信延迟/拒绝承诺都是关于异常处理的。
This is not necessarily the case.
事实未必如此。
A deferred can be rejected for whatever reason your application requires.
无论您的应用程序要求什么原因,延迟都可能被拒绝。
Deferreds/promises are all about handling responses from asynchronous processes, and every asynchronous processes can result in a variety of outcomes - some of which are "successful" and some "unsuccessful". You may choose to reject your deferred - for whatever reason, regardless of whether the outcome was nominally successful or unsuccessful, and without an exception ever having been thrown, either in javascript or in the asynchronous process.
延迟/承诺都是关于处理来自异步进程的响应,每个异步进程都可能导致各种结果——有些是“成功的”,有些是“不成功的”。无论出于什么原因,您都可以选择拒绝您的延迟,无论结果在名义上是成功的还是不成功的,并且没有抛出任何异常,无论是在javascript还是在异步进程中。
You may also choose to implement a timeout on an asynchronous process, in which case you might choose to reject a deferred without a response (successful or unsuccessful) having been received. In fact, for timeouts, this is what you would typically choose to do.
您还可以选择在异步进程上实现超时,在这种情况下,您可以选择拒绝没有收到响应(成功或失败)的延迟。事实上,对于超时,您通常会选择这样做。
#1
14
In general you can think of rejecting as being analogous to a synchronous throw
and fulfilling as being analogous to a synchronous return
. You should reject whenever the function is unsuccessful in some way. That could be a timeout, a network error, incorrect input etc. etc.
通常,您可以将拒绝视为类似于同步抛出,而实现则类似于同步返回。当函数以某种方式失败时,您应该拒绝。这可能是一个超时,一个网络错误,错误的输入等等。
Rejecting a promise, just like throwing an exception, is useful for control flow. It doesn't have to represent a truly unexpected error; it can represent a problem that you fully anticipate and handle:
拒绝一个承诺,就像抛出一个异常一样,对于控制流是有用的。它不一定代表一个真正意想不到的错误;它可以代表一个你完全预料和处理的问题:
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
}
})
}
The rejection lets us jump over the normal success behavior until we get to a method that knows how to handle it. As another example, we might have some function that's deeply nested at the bottom of the applications stack, which rejects. This might not be handled until the very top of the stack, where we could log it. The point is that rejections travel up the stack just like exceptions do in synchronous code.
拒绝让我们跳过正常的成功行为,直到我们找到一个知道如何处理它的方法。作为另一个例子,我们可能有一些深嵌在应用程序堆栈底部的函数,它会拒绝。直到堆栈的最顶端,我们才能对其进行日志记录。关键是拒绝在堆栈中传播,就像同步代码中的异常一样。
In general, wherever possible, if you are struggling to write some asynchronous code, you should think "what would I write if this were synchronous". It's usually a fairly simple transformation to get from that, to the promised equivalent. A nice example of where rejected promises might be used is in an
exists` method:
通常,只要可能,如果您正在努力编写一些异步代码,您应该考虑“如果这是同步的,我将编写什么”。它通常是一个相当简单的变换,从那个变换到承诺的等价变换。anexist的方法中有一个很好的例子说明拒绝的承诺可能被使用:
function exists(filePath) {
return stat(filePath) //where stat gets last updated time etc. of the file
.then(function () { return true; }, function () { return false; })
}
Notice how in this case, the rejection is totally expected and just means the file does not exist. Notice also how it parallels the synchronous function though:
注意,在这种情况下,拒绝是完全可以预期的,这意味着文件不存在。注意它是如何与同步函数平行的:
function existsSync(filePath) {
try {
statSync(filePath);
return true;
} catch (ex) {
return false;
}
}
Your Example
Returning to your example:
回到你的例子:
I would normally chose to reject the promise resulting from findUserByEmail
if no user was found. It's something you fully expect to happen sometimes, but it's the exception from the norm, and should probably be handled pretty similarly to all other errors. Similarly if I were writing a synchronous function I would have it throw
an exception.
如果没有找到用户,我通常会拒绝findUserByEmail的承诺。这是你在某些时候完全期望会发生的事情,但这是常规的例外,应该与所有其他错误处理相似。类似地,如果我在编写一个同步函数,我会让它抛出一个异常。
Sometimes it might be useful to just return null
instead, but this would depend on your applications logic and is probably not the best way to go.
有时只返回null可能有用,但这将取决于应用程序的逻辑,而且可能不是最好的方法。
#2
5
I know where you're coming from. Q and Q documentation can quite easily have you believe that deferred/promise rejection is all about exception handling.
我知道你来自哪里。Q和Q文档可以很容易地让您相信延迟/拒绝承诺都是关于异常处理的。
This is not necessarily the case.
事实未必如此。
A deferred can be rejected for whatever reason your application requires.
无论您的应用程序要求什么原因,延迟都可能被拒绝。
Deferreds/promises are all about handling responses from asynchronous processes, and every asynchronous processes can result in a variety of outcomes - some of which are "successful" and some "unsuccessful". You may choose to reject your deferred - for whatever reason, regardless of whether the outcome was nominally successful or unsuccessful, and without an exception ever having been thrown, either in javascript or in the asynchronous process.
延迟/承诺都是关于处理来自异步进程的响应,每个异步进程都可能导致各种结果——有些是“成功的”,有些是“不成功的”。无论出于什么原因,您都可以选择拒绝您的延迟,无论结果在名义上是成功的还是不成功的,并且没有抛出任何异常,无论是在javascript还是在异步进程中。
You may also choose to implement a timeout on an asynchronous process, in which case you might choose to reject a deferred without a response (successful or unsuccessful) having been received. In fact, for timeouts, this is what you would typically choose to do.
您还可以选择在异步进程上实现超时,在这种情况下,您可以选择拒绝没有收到响应(成功或失败)的延迟。事实上,对于超时,您通常会选择这样做。