19

我正在考虑什么时候我需要拒绝一个承诺。我发现了一些关于这个主题的问题,但找不到正确的答案。 我什么时候应该拒绝承诺?

这篇文章 http://howtonode.org/6666a4b74d7434144cff717c828be2c3953d46e7/promises 说:

  • Resolve:成功的 Promise 是“resolved”,它调用正在等待的成功侦听器并记住为附加的未来成功侦听器解析的值。分辨率与返回值相关。
  • Reject:当遇到错误条件时,Promise 被“拒绝”,它调用正在等待的错误侦听器并记住被拒绝的值以供将来附加的错误侦听器使用。拒绝与抛出的异常相关。

这是原则指导吗?只有在发生异常时才拒绝承诺?

但如果是这样的功能

findUserByEmail()

我希望该函数返回一个用户,这样我就可以在不验证结果的情况下继续这个链

findUserByEmail()
    .then(sendWelcomeBackEmail)
    .then(doSomeNiceStuff)
    .then(etc..)

什么是最佳/常见做法?

4

2 回答 2

22

一般来说,您可以认为拒绝类似于同步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,但这取决于您的应用程序逻辑,可能不是最好的方法。

于 2013-06-25T13:12:50.337 回答
5

我知道你从哪里来。Q 和 Q 文档可以很容易地让你相信延迟/承诺拒绝都是关于异常处理的。

情况不一定如此。

无论您的申请需要什么原因,延期都可能被拒绝。

延迟/承诺都是关于处理来自异步进程的响应,每个异步进程都可能导致各种结果——其中一些是“成功的”,一些是“不成功的”。您可以选择拒绝您的延迟 - 无论出于何种原因,无论结果名义上是成功还是不成功,并且在 javascript 或异步过程中都没有抛出异常。

您还可以选择在异步进程上实现超时,在这种情况下,您可以选择拒绝延迟而没有收到响应(成功或不成功)。事实上,对于超时,这是您通常会选择做的事情。

于 2013-06-25T11:04:23.977 回答