这很可能是一个微不足道的问题。在我的JavaScript中,我有一个功能,可以执行很多操作,我想用进度更新视图。我有一个self.message = ko.observable()
,我在函数执行期间不断更新。
这与我视图中的div
元素绑定。我希望每次ko.observable
更新时都会更新视图。
但是,这不会发生。它仅在函数完成执行时显示“消息”的最后一个值。
如何使用knockoutjs
显示进度更新消息?
代码如下:
在js文件中
self.message = ko.observable("");
self.myfunction = function()
{
self.message("start function");
....
self.message("end function");
}
视图中的
<div data-bind="text: vm.message"></div>
由于 马丁
答案 0 :(得分:1)
你只看到self.message的最后一个值的原因是你的长期运行的JavaScript函数可能同步执行。您的Web应用程序在单个线程中工作,因此在JavaScript执行完毕之前,UI不会更新。
从您的描述中可以看出,您的长时间运行任务已经分步完成,因为在您之间您有(尝试)更新UI的时刻。让UI有机会重绘的最简单方法是使用setTimeout,超时为1 ms。这将使UI有机会赶上。
这是一些丑陋的示例代码:
self.myfunction = function()
{
self.message("start function");
setTimeout(function () {
subTask1();
self.message("subtask1 complete");
setTimeout(function () {
subTask2();
self.message("subtask2 complete");
setTimeout(function () {
subTask3();
self.message("function complete");
}, 1);
}, 1);
}, 1);
}
等。你明白了。您可能希望将其重构为辅助函数,甚至更好地利用promises来链接代码。重点是您需要在重载任务之间创建时间来更新UI。
这是一些未经测试的代码,它们将批量运行一系列任务。您可以传递要在每个批次中运行的任务量。我没有测试过代码,但它应该非常准确。我已经设置了一些可在UI中使用的observable。例如,可观察的“进度”将显示一个百分比,您可以将其用于进度条。
var done = ko.observable(0),
total = ko.observable(0),
progress = ko.computed(function () {
return Math.round(done() / total()) + '%';
});
function executeBatch(tasks, amount, startAt) {
// If startAt is not set, start at the first task
startAt = startAt || 0;
// Stop condition: all tasks are done
if (tasks.length - 1 < startAt) {
return;
}
// Execute the amount of tasks you want to run in 1 batch, or less if there aren't enough tasks left.
for (var i = 0; i < Math.min(startAt + amount, tasks.length); i++) {
doTask(tasks[i]);
}
// Update the UI
done(startAt + amount);
// Give the UI time to update, then recursively call this function to continue executing tasks
setTimeout(function () {
executeBatch(tasks, amount, startAt + amount);
}, 1);
}
function executeAllTasks(tasks) {
// Reset the observables
done(0);
total(tasks.length);
// Start doing the work, 10 tasks at a time
executeBatch(tasks, 10);
}