AngularJS:为什么以及何时需要调用 $timeout?

标签 angularjs angularjs-directive angular-ui-bootstrap angularjs-timeout

Live Demo

我创建了一个 confirmationDialogHeader 指令,其使用方式如下:

<ul>
  <li ng-repeat="item in items">
    {{item}}
    <button class="btn btn-mini" 
            confirmation-dialog-header="Delete Item" 
            confirmation-dialog-action="deleteItem($index)">
      Delete
    </button>
  </li> 
</ul>

当单击按钮时,应该打开一个确认对话框,如果用户确认,则应该调用deleteItem($index),并关闭对话框。

我的问题是最后一点:关闭对话框

这是 Controller (CoffeeScript):

app.controller 'AppCtrl', ['$scope', '$q', '$timeout', ($scope, $q, $timeout) ->
  $scope.items = ['Item 1', 'Item 2'] 
  $scope.deleteItem = (index) ->                         
    deferred = $q.defer()
    $timeout ->
      $scope.items.splice(index, 1)   # All good if this line is removed
      deferred.resolve()
    , 1000
    deferred.promise
]

这是指令:

app.directive 'confirmationDialogHeader', ['$compile', '$q', ($compile, $q) ->
  restrict: 'A'
  scope:
    confirmationDialogAction: '@'
  controller: ($scope) ->
    $scope.onConfirm = ->
      $scope.$parent.$eval($scope.confirmationDialogAction).then ->
        $scope.confirmationDialog = off   # Why this doesn't close the dialog?
  link: (scope, element, attrs) -> 
    $confirmationDialog = $ """
      <div modal="confirmationDialog">
        <div class="modal-header">
          <h4>#{attrs.confirmationDialogHeader}</h4>
        </div>
        <div class="modal-body">
          Are you sure?
        </div>
        <div class="modal-footer">
          <button class="btn" ng-click="confirmationDialog = false">
            Cancel
          </button>
          <button class="btn" ng-click="onConfirm()">
            Yes
          </button>
        </div>
      </div>
    """

    $(document.body).append($confirmationDialog)
    $compile($confirmationDialog)(scope)

    $(element).click ->
      scope.$apply ->
        scope.confirmationDialog = yes  

]

As you can see ,在 deleteItem() 完成并执行 $scope.confirmationDialog = off 后,对话框未关闭

有趣的是,如果 $scope.items.splice(index, 1)$timeout 包装,则对话框 正确关闭!

$timeout ->
  $scope.items.splice(index, 1)

为什么这里需要这个 $timeout 包装?

是否有任何关于何时应该使用 $timeout 包装代码的指南?


Working version of this directive that uses $dialog.


最佳答案

Are there any guidelines about when should we wrap code with $timeout?

$timeout 用作 native setTimeout 的替代品。相对于 native 超时的优点是它在 try/catch block 中运行回调,并且发生的任何错误都将转发到您的应用程序的异常处理程序服务。

但是,从我玩你的演示来看,这不是我看到的问题,并且代码可以简化。

更新 我希望使用模式对话框来实现您的具体实现,但我没有太多运气。因此使用 $dialog 服务而不是模态指令来实现它。也许会有帮助 - here it is

此外,在您的原始版本中,我发现当您单击"is"关闭对话框时,范围正在更新,并且它发生在摘要内,因此它应该触发任何观察程序,从而关闭对话框。在这方面,我看不出它在我的浏览器中因任何原因而不起作用的原因,无论是否使用超时都没有区别。

关于AngularJS:为什么以及何时需要调用 $timeout?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17025321/

相关文章:

javascript - 动态添加时,第二个 Google map 无法正确呈现

javascript - 如何在指令中设置 ng-model 的正确范围?

javascript - 计算 grunt 观看的文件数

javascript - 具有隔离范围的指令内的 Angular 形式

angularjs - Angular bootstrap datepicker日期格式不格式化ng-model值

javascript - UI-Bootstrap 多个可折叠项

javascript - Angular - 从 CMS 延迟加载整个页面

javascript - 使用 Firebase 作为 AngularJS 和 NodeJS 之间的中介是一个 'bad' 想法吗?

javascript - 如何在我的 angularjs 指令中切换 contenteditable 等属性的值?

javascript - 从链接修改指令模板内的 ng-show