何时拒绝/解决承诺

时间:2013-06-25 09:20:45

标签: node.js promise q

我正在考虑何时需要拒绝承诺。 我发现了一些关于这个主题的问题,但找不到合适的答案。 When should I reject a promise?

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

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

这是主要原则吗? 如果发生异常,那个人只会拒绝承诺吗?

但是在像

这样的功能的情况下
findUserByEmail()

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

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

什么是最佳/常见做法?

2 个答案:

答案 0 :(得分:18)

一般来说,您可以将拒绝视为类似于同步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
      }
    })
}

拒绝让我们跳过正常的成功行为,直到我们找到一个知道如何处理它的方法。作为另一个例子,我们可能有一些深深嵌套在应用程序堆栈底部的函数,它拒绝。这可能直到堆栈的最顶层才能处理,我们可以在其中记录它。关键是拒绝就像在同步代码中的例外情况一样向上移动。

一般来说,只要有可能,如果你正在努力编写一些异步代码,你应该想“如果这是同步的话我会写什么”。这通常是一个相当简单的转变,从中获得承诺的等价物。

可能使用被拒绝的承诺的一个很好的例子是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可能会有用,但这取决于您的应用程序逻辑,可能不是最好的方法。

答案 1 :(得分:5)

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

情况不一定如此。

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

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

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