【问题标题】:angularjs - promise never resolved in controllerangularjs - 承诺永远不会在控制器中解决
【发布时间】:2013-01-10 05:37:31
【问题描述】:

在我的控制器中,我得到了另一个服务的承诺。我在其中添加了一个“then”子句,但从未调用过“then”。

看到这个插件:http://plnkr.co/edit/dX0Oz1?p=preview (javascript version)

'fakeLongRunningPromise' 创建一个承诺,在 2 秒后自行解决。

在控制器本身中,一旦承诺得到解决,我就会向控制台发送一条注释。

我可以说承诺正在解决,因为它输出到控制台的“正在解决的承诺”。为什么不输出“promise resolved”?

认为由于控制器返回,promise 可能会“超出范围”?

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    AngularJS 的 promise 解析结果在 $digest 循环内异步传播。因此,使用then 注册的回调只会在进入 $digest 循环时被调用。 setTimeout 在“AngularJS 世界之外”执行,因此不会触发回调。

    解决方案是使用Scope.$apply$timeout 服务。这是带有 $apply 的版本:

          window.setTimeout(function() {
            console.log("Resolving promise");
            $scope.$apply(function(){
              deffered.resolve("worked");
            });
          }, 2000);
    

    这是一个固定的 plunk (JavaScript):http://plnkr.co/edit/g5AnUK6oq2OBz7q2MEh7?p=preview

    【讨论】:

    • 感谢 Pawel,我的实际案例没有使用 setTimeout,但它需要一个 $digest 循环这一事实很有趣——没想到会这样。可能是问题的一部分。所以每次使用(比如)$http.get(),除非有摘要,否则不会触发结果承诺?看起来很奇怪。
    • $http 调用 $digest 循环(通过调用 $apply),对于 DOM 事件和 $timeout 服务也是如此。因此,一旦您在 AngularJS 世界中解决了 Promise,结果就会立即传播,而无需手动调用 $apply。因此,实际上需要 $digest 来传播解决/拒绝结果,但大多数时候您看不到这一点,因为 AngularJS 负责调用 $apply。
    • 嗯。在我的实际情况中,我使用的是 $http 但我的控制器函数中的承诺无法解决。只有当我将它们放入 $scope 函数时,它们才能解决。我会继续努力,但我认为 $digest 是关键。再次感谢。
    • 不错的 $scope.$apply。将我的新链式承诺包装在 $apply 中,它就像一个魅力。呸!
    • @Roy,我真的不清楚为什么在使用 $http 时需要使用 $apply - 如果我理解正确的话,通常不需要这样做。如果您可以在 AngularJS 邮件列表上发布您的实际代码,我可以看看。
    【解决方案2】:

    我使用了$timeout 而不是setTimeout,它可以工作:

     # Resolve the promise after 2 seconds
      $timeout( ()->
        console.log "Resolving promise"
        deffered.resolve ("worked")
      , 2000)
    

    【讨论】:

    • 当然可以,因为 $timeout 只是调用 $apply 的 setTimout。换句话说,是 $timeout 服务触发了一个摘要循环。但这里的重点是,只有当您处于 AngularJS 摘要周期时,才会传播承诺解析的结果。
    • 感谢您的解释。
    猜你喜欢
    • 1970-01-01
    • 2016-05-06
    • 2019-11-29
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 2020-04-15
    • 1970-01-01
    相关资源
    最近更新 更多