Подтвердить что ты не робот

Angular JS: цепочка promises и цикл дайджеста

ПРИМЕЧАНИЕ. скрипта использует старую версию Angular и что она больше не работает, поскольку с 1.2 механизм шаблона Angular не обрабатывает прозрачно promises.

Я просматриваю цепочку promises, чтобы заполнить область видимости, а затем автоматически обновить область.

У меня возникают проблемы с этим, хотя... Если я назову "тогда" по уже разрешенному обещанию, он создаст новое обещание (которое вызовет функцию успеха асинхронно, но почти сразу). Я думаю, проблема заключается в том, что мы уже покинули цикл дайджеста к моменту вызова функции успеха, поэтому dom никогда не обновляется.

Вот код:

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

Есть ли способ сделать эту работу без вызова $apply каждый раз, когда я связываю promises?

4b9b3361

Ответ 1

ПРИМЕЧАНИЕ: скрипта использует старую версию Angular и что она больше не работает, поскольку с 1.2 механизм шаблона Angular не обрабатывает прозрачно promises.

В quote @pkozlowski.opensource:

В AngularJS результаты решения обещания распространяются асинхронно, в цикле $digest. Таким образом, обратные вызовы, зарегистрированные с помощью then(), будут вызваны только при вводе цикла $digest.

Итак, когда кнопка нажата, мы находимся в цикле дайджеста. then() создает новое обещание, но результаты этого then() не будут распространяться до следующего цикла дайджеста, который никогда не наступает (поскольку для запуска одного из них не существует $timeout или $http или DOM-событие). Если вы добавите еще одну кнопку с ng-click, которая ничего не делает, тогда щелкните по ней, это вызовет цикл дайджеста, и вы увидите результаты:

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

Здесь fiddle, который делает это.

Сценарий также использует $timeout вместо setTimeout - тогда $apply() не требуется.

Надеюсь, это понятно, когда вам нужно использовать $apply. Иногда вам нужно вызвать его вручную.