如何在执行过程中使 angular 刷新屏幕
How to make angular refresh screen in the middle of execution
我在第三页有一点 angular html。
一切正常,代码正常工作,指令正常工作("ng-show" 除外,它从不工作,但这在这里无关紧要)。
但我有一个繁重的代码,需要单击按钮才能运行(使用 ng-click
)。在执行过程中,一切都冻结了,好吧,这是预料之中的。
但我非常希望在执行过程中出现一个"img",但似乎在代码期间没有更新任何东西(代码之后一切都完美更新,但在代码)。
如何才能"refresh"angularhtml"during"执行"ng-click"中的代码?
我试过“$scope.apply()”和“$scope.digest()”,但两者都会在控制台中导致一些奇怪的错误....
编辑
感谢以下答案:错误确实是因为 "apply/digest" 已经在进行中。通过使用所示的异步方法,我可以毫无问题地使用 "apply"。
对图像进行 ng-show 怎么样?您可以使用 div 来占据您希望显示带有
的图像的整个部分
<div ng-show="loading" class="some-class-to-display-image"></div>
然后在您的 js 中转 $scope.loading = true;
,同时您正在处理/拨打电话等。您可以使用承诺并在您的请求中使用 .finally()
并将 $scope.loading = false;
设置为停止动画。
将您要首先执行的代码包装在 $scope.apply() 中应该可以工作,除非您收到“$digest already in progress”错误,该错误仅在一个摘要循环中发生 运行一次。
如果是这种情况,您可以尝试在 $timeout 或 $evalAsync(Angular v1.2.x & above) 中显示加载图像后包装要执行的代码,这将确保 2 个摘要周期不会冲突,即
$scope.$apply(function () {
//display loading image code
});
//Other code
或
//display loading image code
$scope.$evalAsync(function () {
//Other code
});
JavaScript在浏览器环境中的工作方式是javascript的一个块执行直到完成,无论你是否使用AngularJS,浏览器都不会呈现中间结果或香草 JavaScript.
例子
假设您对 10.000 个数据条目进行了繁重的工作并希望显示进度条:
startButton.onclick = function onStartClick() {
var progressbar = document.getElementById('progressbar');
progressbar.style.width = "0";
// process 100000 entries, update progress bar between
for (var n = 0; n < 100000; y++) {
doSomethingWithEntryNumber(n);
progressbar.style.width = (n / 100000) + "%";
}
}
它不会像预期的那样更新浏览器中的进度条 div
,但会冻结浏览器直到 onDivClick
完成。这与 AngularJS 没有什么不同,处理大量数据不会更新您的 UI。
要处理大量数据,您需要拆分工作并使用任何一种 "future"/"promise"/"delay" 技术 - 例如:
startButton.onclick = function onStartClick() {
var progressbar = document.getElementById('progressbar');
progressbar.style.width = "0";
// process 100000 entries in 1000 entry batches, update progress bar between
function processBatch(batch) {
for (var i = 0; i < 1000; i++) {
doSomethingWithEntryNumber(batch*1000 + i);
}
// update progressbar
progressbar.style.width = (batch / 1000) + "%";
if (batch < 99) {
// continue work after browser has updated UI
setTimeout(processBatch.bind(this, batch + 1), 10);
}
}
processBatch(0);
}
这样浏览器可以呈现 UI 变化,用户可以滚动等,同时您仍然能够处理您的 100000 个数据条目。
关于"showing an image during the process",你会显示图像,然后setTimeout
延迟你的工作,当你的工作完成后删除图像并将你的数据设置为$scope
.
不能刷新HTML "during"的执行,因为网页是单线程的,也就是说CPU在计算的时候,不能做其他事情。 (从技术上讲,web worker 可以帮助分叉多个线程,但实际上,您不需要那个)。
所以你想要点击的是说,启用图像,然后等待 angular 用该图像更新 DOM,然后 运行 你的重代码。
要实现这一点,您需要使用 $timeout
服务,这样:
$scope.onClick = function() {
// Set the model to display an image
$scope.displayImage = true;
// Wait for angular to digest the current cycle and update the DOM
$timeout(function() {
// Do heavy stuff, and at the bottom of the code update the model to hide the image
$scope.doHeavyStuff();
$scope.displayImage = false;
});
}
在你的HTML中你只需要
<img ng-show = "displayImage" src = "some_url">
<div ng-hide = "displayImage"> Heavy stuff done :) </div>
现在,如果您在这一步对 ng-show 有疑问,请打开一个不同的问题。
我在第三页有一点 angular html。
一切正常,代码正常工作,指令正常工作("ng-show" 除外,它从不工作,但这在这里无关紧要)。
但我有一个繁重的代码,需要单击按钮才能运行(使用 ng-click
)。在执行过程中,一切都冻结了,好吧,这是预料之中的。
但我非常希望在执行过程中出现一个"img",但似乎在代码期间没有更新任何东西(代码之后一切都完美更新,但在代码)。
如何才能"refresh"angularhtml"during"执行"ng-click"中的代码?
我试过“$scope.apply()”和“$scope.digest()”,但两者都会在控制台中导致一些奇怪的错误....
编辑
感谢以下答案:错误确实是因为 "apply/digest" 已经在进行中。通过使用所示的异步方法,我可以毫无问题地使用 "apply"。
对图像进行 ng-show 怎么样?您可以使用 div 来占据您希望显示带有
的图像的整个部分<div ng-show="loading" class="some-class-to-display-image"></div>
然后在您的 js 中转 $scope.loading = true;
,同时您正在处理/拨打电话等。您可以使用承诺并在您的请求中使用 .finally()
并将 $scope.loading = false;
设置为停止动画。
将您要首先执行的代码包装在 $scope.apply() 中应该可以工作,除非您收到“$digest already in progress”错误,该错误仅在一个摘要循环中发生 运行一次。
如果是这种情况,您可以尝试在 $timeout 或 $evalAsync(Angular v1.2.x & above) 中显示加载图像后包装要执行的代码,这将确保 2 个摘要周期不会冲突,即
$scope.$apply(function () {
//display loading image code
});
//Other code
或
//display loading image code
$scope.$evalAsync(function () {
//Other code
});
JavaScript在浏览器环境中的工作方式是javascript的一个块执行直到完成,无论你是否使用AngularJS,浏览器都不会呈现中间结果或香草 JavaScript.
例子
假设您对 10.000 个数据条目进行了繁重的工作并希望显示进度条:
startButton.onclick = function onStartClick() {
var progressbar = document.getElementById('progressbar');
progressbar.style.width = "0";
// process 100000 entries, update progress bar between
for (var n = 0; n < 100000; y++) {
doSomethingWithEntryNumber(n);
progressbar.style.width = (n / 100000) + "%";
}
}
它不会像预期的那样更新浏览器中的进度条 div
,但会冻结浏览器直到 onDivClick
完成。这与 AngularJS 没有什么不同,处理大量数据不会更新您的 UI。
要处理大量数据,您需要拆分工作并使用任何一种 "future"/"promise"/"delay" 技术 - 例如:
startButton.onclick = function onStartClick() {
var progressbar = document.getElementById('progressbar');
progressbar.style.width = "0";
// process 100000 entries in 1000 entry batches, update progress bar between
function processBatch(batch) {
for (var i = 0; i < 1000; i++) {
doSomethingWithEntryNumber(batch*1000 + i);
}
// update progressbar
progressbar.style.width = (batch / 1000) + "%";
if (batch < 99) {
// continue work after browser has updated UI
setTimeout(processBatch.bind(this, batch + 1), 10);
}
}
processBatch(0);
}
这样浏览器可以呈现 UI 变化,用户可以滚动等,同时您仍然能够处理您的 100000 个数据条目。
关于"showing an image during the process",你会显示图像,然后setTimeout
延迟你的工作,当你的工作完成后删除图像并将你的数据设置为$scope
.
不能刷新HTML "during"的执行,因为网页是单线程的,也就是说CPU在计算的时候,不能做其他事情。 (从技术上讲,web worker 可以帮助分叉多个线程,但实际上,您不需要那个)。
所以你想要点击的是说,启用图像,然后等待 angular 用该图像更新 DOM,然后 运行 你的重代码。
要实现这一点,您需要使用 $timeout
服务,这样:
$scope.onClick = function() {
// Set the model to display an image
$scope.displayImage = true;
// Wait for angular to digest the current cycle and update the DOM
$timeout(function() {
// Do heavy stuff, and at the bottom of the code update the model to hide the image
$scope.doHeavyStuff();
$scope.displayImage = false;
});
}
在你的HTML中你只需要
<img ng-show = "displayImage" src = "some_url">
<div ng-hide = "displayImage"> Heavy stuff done :) </div>
现在,如果您在这一步对 ng-show 有疑问,请打开一个不同的问题。