【问题标题】:How to access result from the previous promise in AngularJS promise chain? [duplicate]如何访问 AngularJS 承诺链中上一个承诺的结果? [复制]
【发布时间】:2013-12-08 13:59:36
【问题描述】:

我有以下代码:

authService.authenticate()
.then(function (user) {
  return Task.all({user: user})
})
.then(function (tasks) {
  // How to access user object here?
})

是否有一些内置方法可以将 user 对象传递给第二个 then 函数,而无需执行以下操作:

var user2 = null;
authService.authenticate()
.then(function (user) {
  user2 = user
  return Task.all({user: user})
})
.then(function (tasks) {
   // Use user2 here
})

或者这个:

authService.authenticate()
.then(function (user) {
  var defer = $q.defer()
  Task.all({user: user}).then(function (tasks) {
    return defer.resolve(user, tasks)
  })
  return defer.promise
})
.then(function (user, tasks) {
   // Use user2 here
})

或者通过直接在Task.all 上调用第二个then 来嵌套它们(这样我就可以通过闭包获得user 对象)? 嵌套它们正是我想要避免的。

【问题讨论】:

    标签: javascript angularjs promise


    【解决方案1】:

    您可以将 then 放在用户仍然可以访问的范围内(检查闭包)

    authService.authenticate()
    .then(function (user) {
      Task.all({user: user})
      .then(function (tasks) {
        // How to access user object here?
      })
    })
    

    从 Kriskowal 的 Q documentation 本身来看,这两种风格是等效的。 Angular 的$q 是基于Q

    唯一的区别是嵌套。如果您需要在闭包中捕获多个输入值,嵌套处理程序很有用。

    【讨论】:

    • 谢谢,但这是我在问题中谈论的第三种情况 - 嵌套它们:) 我试图避免它,因为我只是展示了一个简化的情况 - 在实际代码中有一些更多的承诺,所以嵌套它们就像使用回调一样。
    • 嗯...是的,你是对的。问题是我在我的代码中使用了这种嵌套样式,而且代码真的很大……嵌套的级别并没有那么大。此外,Coffeescript 语法也有很大帮助 ;)
    • 我也在使用 CoffeeScript,所以我会尝试嵌套它们,看看它的样子。虽然我不确定在嵌套承诺的情况下错误处理是如何工作的......
    • 错误冒泡直到发现失败,所以你最后需要失败。
    • @szimek 它的工作方式完全相同,请参阅github.com/kriskowal/q#chaining
    【解决方案2】:

    可以将用户和任务合并到一个对象中传递给下一个then

    authService.authenticate()
    .then(function (user) {
      var defer = $q.defer()
      Task.all({user: user}).then(function (tasks) {
    
        return defer.resolve({user:user, tasks:tasks})
      })
      return defer.promise
    })
    .then(function (data) {
       $scope.user=data.user;
       $scope.tasks=data.tasks;
    })
    

    DEMO

    【讨论】:

    • 谢谢!这就是我在第二个示例中所做的,尽管仅在发布之后,我发现我只能将一个参数传递给defer.resolve,所以我的defer.resolve(user, tasks) 示例有点不正确。这对我来说似乎是最干净的解决方案,虽然需要手动创建一个新的延迟对象,如果你需要,这可能会很糟糕,例如通过整个链传递一个变量。
    • 可以将各个步骤存储在一个服务对象中,最后只返回那个对象
    • 我不熟悉 Q/Angular 承诺,但如果 Task 异步发生,这是否保证 defer 将在第二个时间包含 usertasks 数据then 身体出现了吗?如果我理解正确,defer.resolve() 正在改变defer 对象的状态,那么返回defer.promise 如何知道Task.all then body 是否终止?我正在尝试了解此解决方案的工作原理。
    • -1 在这里使用defer,因为现在你已经悄悄地从Task.all 中删除了错误 - 只需使用return Task.all(...).then(...)
    猜你喜欢
    • 2021-02-18
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-18
    • 2015-01-10
    相关资源
    最近更新 更多