【问题标题】:AngularJS promises not firing when returned from a service [duplicate]AngularJS承诺从服务返回时不会触发[重复]
【发布时间】:2013-01-25 19:52:17
【问题描述】:

可能重复:
angularjs - promise never resolved in controller

我在 AngularJS 服务中封装了一个慢速 WebSockets 服务器,然后从我的控制器调用该服务。如果我将回调链接到回调上,则一切正常,任何 UI 都会异步更新。

当我尝试使用 $q.defer() 来清理那些乱七八糟的回调时,似乎我的 deferred 永远不会被调用。我对 Python 的 Twisted 中的 deferred 的概念很熟悉,所以我认为从概念上讲一切都应该工作 - 但事实并非如此。

这是我能想到的最短示例,使用 setTimeout 函数模拟慢速 WebSockets 服务器。

<!doctype html>

<html ng-app="beta">
    <head>
        <title>Beta</title>
        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
        <script>
            var beta = angular.module('beta', []);

            var BetaCtrl = function ($scope, betaServ) {
                $scope.button = function () {
                    serv_result = betaServ.slow();
                    console.log(serv_result);

                    serv_result.then(function (result) {
                        console.log('callback finished');
                    });
                }
            }

            beta.service('betaServ', function($q) {
                this.slow = function () {
                    d = $q.defer()
                    setTimeout(function () {
                        console.log('before resolve');
                        d.resolve();
                        console.log('after resolve');
                    }, 2000);
                    return d.promise;
                }
            });
        </script>
    </head>
    <body>
        <div ng-controller="BetaCtrl">
            <button ng-click="button()">Run</button>
        </div>    
    </body>
</html>

可能应该如下运行:

  1. 按钮点击
  2. $scope.button() 被调用;它调用 service.slow() 函数
  3. service.slow() 返回一个延迟
  4. 在 deferred 上注册了一个回调
  5. 延迟触发,触发注册的回调(这部分永远不会发生)

有什么想法吗?谢谢。

【问题讨论】:

  • 我尝试将setTimeout 更改为$timeout,它似乎有效!我仍然不明白,因为我没有更新 UI,只是登录到控制台。而且,在我的情况下它仍然没有帮助,因为原始代码中的延迟不是因为 setTimeout,而是因为 WebSockets 请求。

标签: angularjs future deferred


【解决方案1】:

您需要使用 $apply 调用回调,因为它是在 Angular 之外调用的。由于这是一项服务,因此您需要在服务中包含 $rootScope:

beta.service('betaServ', function($q, $rootScope) {
    this.slow = function () {
        d = $q.defer()
        setTimeout(function () {
            console.log('before resolve');
            $rootScope.$apply(d.resolve);
            console.log('after resolve');
        }, 2000);
        return d.promise;
    }
});

【讨论】:

  • 谢谢,解决了!我尝试将$scope注入到服务中,然后调用$apply,但似乎无法注入$scope。从来没有考虑过 $rootScope。尽管如此,我认为 Angular 现在会以某种方式调用 deferred,而无需显式 $apply。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多