Angularjs ng-show с обещанием

Я использую ng-show с выражением, которое разрешает обещание, которое разрешает логическое. Когда я это делаю, я получаю переполнение итераций 10 дайджеста.

См. http://plnkr.co/edit/XibYM0kCnXhKjNUeTsp3?p=preview

  <body ng-controller="MainCtrl">
    <p ng-show="returnsABoolean()">non promise</p>
    <p ng-show="returnsAPromiseThatResolvesToABoolean()">promise</p>
  </body>

Ctrl

  $scope.returnsABoolean = ()->
    true

  $scope.returnsAPromiseThatResolvesToABoolean = ()->
    $q.when(false)

Я знаю, что {{somePromise}} будет разрешен, но {{returnsAPromiseThatResolvesToABoolean()}}, похоже, вызывает ту же проблему.

Любые идеи? Я ожидаю, что это сработает.

Ответ 1

AngularJS автоматически разрешает обещание привязки шаблона. Тем не менее, вы должны использовать обещание в ng-init, чтобы не допустить, чтобы цикл дайджеста возвращал новое обещание каждый тик.

<p ng-init="v=returnsAPromiseThatResolvesToABoolean()" ng-show="v">promise</p>

Ответ 2

Plunker: http://plnkr.co/edit/NvjP5qHafhyIWXXotBej?p=preview

Это работает так, как я думаю, вы намеревались это сделать. $q.when() возвращает объект обещания, поэтому ng-show не получает логическое значение; он получает объект обещания.

Обновлен шаблон:

  <body ng-controller="MainCtrl">
    <p ng-show="returnsABoolean()">non promise</p>
    <p ng-show="returnsAPromiseThatResolvesToABoolean">promise</p>
  </body>

Обновлен Ctrl:

  $scope.returnsABoolean = ()->
    true

  promise = $q.when(false)
  promise.then((val) ->
    $scope.returnsAPromiseThatResolvesToABoolean = val)

Ответ 3

Если вы посмотрите источники здесь, вы увидите, что обещание разрешено в nextTick, поэтому только $scope изменяется в следующий раз angular делает цикл $digest. Но ваша функция возвращает новое обещание в каждом цикле $digest, никогда не получая разрешенное значение предыдущего обещания.

Здесь также обсуждалась старая проблема .

Вы можете решить эту проблему, сохранив "постоянную" ссылку на свое обещание вне функции, как я сделал здесь.