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?
Ответы
Ответ 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. Иногда вам нужно вызвать его вручную.