Angular JS:链接承诺和摘要周期

时间:2022-05-15 11:42:04

NOTE: the fiddle uses an old version of Angular, and that it's not working any more because as of 1.2 the Angular template engine does not handle promises transparently.

I'm looking into chaining promises to populate my scope, and then having the scope automatically update the dom.

我正在寻找链接承诺来填充我的范围,然后让范围自动更新dom。

I'm running into problems with this though.. If I call "then" on an already resolved promise, it creates a new promise (that will call the success function asynchronously but almost immediately). I think the problem is that we've already left the digest cycle by the time the success function is called, so the dom never updates.

我遇到了这方面的问题..如果我在已经解决的承诺上调用“then”,它会创建一个新的承诺(它将异步调用成功函数,但几乎立即调用)。我认为问题是我们已经在调用成功函数时离开了摘要周期,所以dom永远不会更新。

Here is the code:

这是代码:

<div ng-controller="MyCtrl">
    Hello, {{name}}! <br/>
    {{name2}}<br/>
    <button ng-click="go()">Clickme</button><br/>
    {{name3}}
</div>

var myApp = angular.module('myApp',[]);

function MyCtrl($scope, $q) {
    var data = $q.defer();    
    setTimeout(function() {$scope.$apply(data.resolve("Some Data"))}, 2000);
    var p = data.promise;

    $scope.name = p.then(angular.uppercase);
    $scope.name2 = p.then(function(x) { return "Hi "+x;});
    $scope.go = function() {
            $scope.name3 = p.then(function(x) { 
                // uncomment this to make it work:
                //$scope.$apply();
                return "Finally: "+x;
            });
    };
 }

http://jsfiddle.net/QZM4d/

http://jsfiddle.net/QZM4d/

Is there some way to make this work without calling $apply every time I chain promises?

有没有办法让这项工作没有在每次我链接承诺时调用$ apply?

1 个解决方案

#1


15  

NOTE: the fiddle uses an old version of Angular, and that it's not working any more because as of 1.2 the Angular template engine does not handle promises transparently.

To quote @pkozlowski.opensource:

引用@ pkozlowski.opensource:

In AngularJS the results of promise resolution are propagated asynchronously, inside a $digest cycle. So, callbacks registered with then() will only be called upon entering a $digest cycle.

在AngularJS中,承诺解析的结果在$ digest周期内异步传播。因此,只有在进入$ digest循环时才会调用then()注册的回调。

So, when the button is clicked, we are in a digest cycle. then() creates a new promise, but the results of that then() will not be propagated until the next digest cycle, which never comes (because there is no $timeout, or $http, or DOM event to trigger one). If you add another button with ng-click that does nothing, then click that, it will cause a digest cycle and you'll see the results:

因此,当单击按钮时,我们处于摘要周期。 then()创建一个新的promise,但then()的结果将不会传播,直到下一个摘要周期,从未到来(因为没有$ timeout,$ http或DOM事件触发)。如果你添加另一个没有任何操作的ng-click按钮,然后点击它,它将导致一个摘要周期,你会看到结果:

<button ng-click="">Force digest by clicking me</button><br/>

Here's a fiddle that does that.

这是一个小提琴,这样做。

The fiddle also uses $timeout instead of setTimeout -- then $apply() isn't needed.

小提琴也使用$ timeout而不是setTimeout - 然后不需要$ apply()。

Hopefully it is clear when you need to use $apply. Sometimes you do need to call it manually.

希望你需要使用$ apply时很清楚。有时您需要手动调用它。

#1


15  

NOTE: the fiddle uses an old version of Angular, and that it's not working any more because as of 1.2 the Angular template engine does not handle promises transparently.

To quote @pkozlowski.opensource:

引用@ pkozlowski.opensource:

In AngularJS the results of promise resolution are propagated asynchronously, inside a $digest cycle. So, callbacks registered with then() will only be called upon entering a $digest cycle.

在AngularJS中,承诺解析的结果在$ digest周期内异步传播。因此,只有在进入$ digest循环时才会调用then()注册的回调。

So, when the button is clicked, we are in a digest cycle. then() creates a new promise, but the results of that then() will not be propagated until the next digest cycle, which never comes (because there is no $timeout, or $http, or DOM event to trigger one). If you add another button with ng-click that does nothing, then click that, it will cause a digest cycle and you'll see the results:

因此,当单击按钮时,我们处于摘要周期。 then()创建一个新的promise,但then()的结果将不会传播,直到下一个摘要周期,从未到来(因为没有$ timeout,$ http或DOM事件触发)。如果你添加另一个没有任何操作的ng-click按钮,然后点击它,它将导致一个摘要周期,你会看到结果:

<button ng-click="">Force digest by clicking me</button><br/>

Here's a fiddle that does that.

这是一个小提琴,这样做。

The fiddle also uses $timeout instead of setTimeout -- then $apply() isn't needed.

小提琴也使用$ timeout而不是setTimeout - 然后不需要$ apply()。

Hopefully it is clear when you need to use $apply. Sometimes you do need to call it manually.

希望你需要使用$ apply时很清楚。有时您需要手动调用它。