AngularJS 如何在 setTimeout 后强制更新 DOM

AngularJS How to force DOM update after setTimeout

下面的代码块等待超时,然后执行带有承诺的 HTTP 请求,然后根据响应更改 Angular Material 范围变量。在输入字段上使用 ng-change 调用它。我的 HTML 中也有一个带有 ng-hide="showStuff" 的元素,显然,当 $scope.showStuff 变为 false 时,我希望它立即消失。不幸的是,它实际上并没有消失,直到我 select 在 DOM.

中的其他内容

我之前使用 promises 来更改 DOM 中的内容,并且效果很好。为什么 DOM 不自行更新,我该如何解决?

$scope.checkSomething = function() {
    // Use a timeout to prevent a checks from going off too rapidly
    if (queryTimeout) {
        clearTimeout(queryTimeout);
    }
    queryTimeout = setTimeout(function() {
        bluebird.bind({}).then(function() {
            return makeHttpRequest();
        }).then(function(res) {
            $scope.showStuff = res.data.length > 0;
        })
    }, 500);
}

AngularJs 的变化检测(称为 "digest cycle")不知道 运行,除非代码开始在 angular 上下文中执行。所以异步的东西不能很好地工作。这就是为什么 angular 提供诸如 $timeout、$interval 和 $q 之类的服务来执行异步操作,从而为您处理摘要周期的启动。使用那些,这种问题将非常罕见。

如果您想使用 $q 以外的其他类型的承诺,您需要手动启动摘要循环。如果您希望它很快发生,您可以使用 $scope.$apply() if you want it to happen immediately, or $scope.$applyAsync 来执行此操作,但不是同步的(如果您可能有多个调用它并且您希望它们一起批处理时很有用)。

所以如果你不想使用 $timeout 和 $q,你必须这样做:

setTimeout(function() {
    bluebird.bind({}).then(function() {
        return makeHttpRequest();
    }).then(function(res) {
        $scope.showStuff = res.data.length > 0;
        $scope.$apply();
    })
}, 500);

使用 $timeout 服务,它 returns 一个与 AngularJS 执行上下文及其摘要周期集成的承诺:

$scope.checkSomething = function() {
    // Use a timeout to prevent a checks from going off too rapidly
    if (queryTimeout) {
        $timeout.cancel(queryTimeout);
    }
    queryTimeout = $timeout(function() {
        return makeHttpRequest();
    }, 500);

    queryTimeout.then(function(res) {
        $scope.showStuff = res.data.length > 0;
    })
}

这将使 makeHttpRequest 的执行延迟 500 毫秒。 $timeout 服务 returns 用于解析来自服务器的数据的承诺。

AngularJS 通过提供自己的事件处理循环来修改正常的 JavaScript 流程。这将 JavaScript 分为经典和 AngularJS 执行上下文。只有在 AngularJS 执行上下文中应用的操作才能受益于 AngularJS 数据绑定、异常处理、属性 监视等

通过使用 AngularJS $超时服务,包装的 setTimeout 将在 AngularJS 执行上下文中执行。

有关详细信息,请参阅