下面的代码块等待超时,然后执行带有承诺的HTTP请求,然后根据响应更改Angular Material范围变量。在输入字段中使用ng-change
进行调用。我的HTML中也有一个带有ng-hide="showStuff"
的元素,很明显,当$scope.showStuff
变为false时,我希望它立即消失。不幸的是,直到我在DOM中选择其他内容,它才真正消失。
在更改DOM中的内容之前,我已经使用了promises,并且它们工作正常。为什么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);
}
答案 0 :(得分:2)
除非代码开始在角度上下文中执行,否则不对AngularJs进行更改检测(称为“摘要循环”)。因此,异步事情并不能很好地工作。这就是为什么angular提供$ timeout,$ interval和$ q之类的服务来执行异步操作的方式,以便它为您处理摘要周期的开始。使用这些,这种类型的问题将极为罕见。
如果您要使用$ q以外的其他类型的Promise,则需要手动启动摘要周期。如果希望立即发生,可以使用$scope.$apply()进行操作,如果希望很快发生,可以使用$scope.$applyAsync进行操作,但不能同步进行(如果您有很多事情在调用它,并且您希望将它们分批处理。)
因此,如果您不想使用$ timeout和$ q,则必须执行以下操作:
setTimeout(function() {
bluebird.bind({}).then(function() {
return makeHttpRequest();
}).then(function(res) {
$scope.showStuff = res.data.length > 0;
$scope.$apply();
})
}, 500);
答案 1 :(得分:1)
使用$timeout
服务,它返回一个与AngularJS执行上下文及其摘要周期集成的promise:
$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服务返回一个承诺,用于解决服务器中的数据。
AngularJS通过提供自己的事件处理循环来修改常规JavaScript流。这将JavaScript分为经典和AngularJS执行上下文。只有在AngularJS执行上下文中应用的操作才能受益于AngularJS数据绑定,异常处理,属性监视等。
通过使用AngularJS $ timeout服务,将在AngularJS执行上下文中执行包装的setTimeout
。
有关更多信息,请参见