【问题标题】:Alternative to promises of asynchronous callouts?替代异步标注的承诺?
【发布时间】:2018-04-08 10:57:41
【问题描述】:

假设我们有一个简单的前端和(如果重要的话我们假设 Angular)和一个后端应用程序。假设前端应用程序执行get 请求。通常,角度存储库发出$http.get 请求,该请求返回一个承诺(角度 1)或可以转换为承诺(角度 2 或 4)的可观察对象,然后存储库返回该承诺。然后角度服务看起来像

repository.makeTheGetCall().then(function (response) {
  // process response
}); 

这通常很好。

1) 但是如果服务上的所有逻辑都依赖于这个 1 调用呢?然后我们基本上将整个服务嵌套在一个 .then 子句中。

2) 或者如果基于第一个 Get 请求的响应,我们发出另一个请求。基于该响应,我们提出另一个请求,依此类推。然后我们将有一堆 then 子句链接起来。

这两种情况似乎都不罕见,而且都导致了看起来“丑陋”的代码。是否有任何其他做法可以用来允许异步调用但不必将承诺从存储库层返回到服务层?

谢谢你:)

【问题讨论】:

  • 您不必将所有代码都放在一个函数中。您可以创建从 .then 回调函数内部调用的其他函数。 #2对我来说听起来不是问题。 Promise 被设计成链式的。 (这是丑陋的替代方案:嵌套回调)
  • "然后我们基本上将整个服务嵌套在 .then 子句中。" - 是的,因为从逻辑上讲,这就是您想要的:服务仅在要求。当然,您不必在语法上将整个代码嵌套在那里。
  • "然后我们将有一堆链接的 then 子句。" - 是的,这就是 whole point of promises(和 observables):它们是一元的,所以你可以它们而不是嵌套它们。
  • 如果您不喜欢 then 调用的“丑陋”,请查看 async/await 语法。

标签: javascript angularjs asynchronous promise repository-pattern


【解决方案1】:

您可以使用async/await。它是经典 .then() 承诺处理的唯一替代方案。

所以,不要这样做:

someServiceMethod() {
  repository.makeTheGetCall().then(function (response) {
    // process response
  }); 
}

你可以这样做:

async someServiceMethod() {
  const response = await repository.makeTheGetCall()
  // process response
}

最酷的是我们没有任何“回调地狱”的起点,代码现在是平坦的(您列表中的#1)

此外,如果其中一个 Promise 被拒绝,我们可以处理 try/catch 块中的错误。这样做的好处是我们可以在一个地方捕获所有错误。 (在您的列表中排名第 2):

async someServiceMethod() {
  try {  
    const response = await repository.makeTheGetCall()
    const data = await repository.getDataForResponse(response)
    // process data or make another async call
  } catch (err) {
    // process error
  }
}

Good explanation of how to use it

【讨论】:

  • "在 try/catch 块中包装包含 await 的代码行也是一个好习惯" - 不。正如将.catch() 放在每个返回承诺的函数调用上不是一个好习惯一样。当你想要处理错误时,你应该只使用catch(任何一个),否则就让它冒泡给你的调用者。
  • 请记住,异步回调中的错误无法通过 try 和 catch 进行外部拦截和处理,如下所述:frontnet.eu/…
猜你喜欢
  • 2016-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-01
  • 2017-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多