Angular JS:链接承诺和摘要循环 [英] Angular JS: Chaining promises and the digest cycle

查看:21
本文介绍了Angular JS:链接承诺和摘要循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:小提琴使用旧版本的 Angular,它不再工作,因为从 1.2 开始,Angular 模板引擎不能透明地处理承诺.

我正在研究链接 promise 以填充我的范围,然后让范围自动更新 dom.

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

代码如下:

你好,{{name}}!<br/>{{name2}}<br/><button ng-click="go()">Clickme</button><br/>{{name3}}

var myApp = angular.module('myApp',[]);函数 MyCtrl($scope, $q) {var 数据 = $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) {//取消注释以使其工作://$scope.$apply();return "最后:"+x;});};}

http://jsfiddle.net/QZM4d/

有什么方法可以不用每次我链接 promise 时都调用 $apply 吗?

解决方案

注意:小提琴使用旧版本的 Angular,并且它不再工作,因为从 1.2 开始,Angular 模板引擎不透明地处理承诺.

引用@pkozlowski.opensource:

<块引用>

在 AngularJS 中,promise 解析的结果在 $digest 循环内异步传播.因此,使用 then() 注册的回调只会在进入 $digest 循环时调用.

因此,当单击按钮时,我们处于摘要循环中.then() 创建了一个新的 promise,但是 then() 的结果直到 next 摘要循环才会传播,这个循环永远不会出现(因为没有 $timeout、$http 或 DOM事件触发).如果您使用 ng-click 添加另一个什么都不做的按钮,然后单击该按钮,它将导致摘要循环,您将看到结果:

<button ng-click="">点击我强制摘要</button><br/>

这里有一个 fiddle 可以做到这一点.

小提琴也使用 $timeout 而不是 setTimeout -- 那么 $apply() 就不需要了.

希望您清楚何时需要使用 $apply.有时您确实需要手动调用它.

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.

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.

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/

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

解决方案

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:

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.

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:

<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.

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

这篇关于Angular JS:链接承诺和摘要循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆