Когда у вас много обработки на стороне клиента, вам нужно разделить свою работу на отдельные потоки.В браузере есть только один поток для обработки пользовательского ввода (событий) и для обработки JS.Если вы обрабатываете слишком много JS, не уступая, пользовательский интерфейс перестает отвечать на запросы, а браузер недоволен.
Как вы можете позволить своему скрипту работать?Новый способ заключается в использовании веб-работников http://www.whatwg.org/specs/web-workers/current-work/.Это работает путем создания отдельного потока для запуска JS, поток потока не имеет доступа к DOM и может выполняться одновременно.
Однако эта новая технология существует не во всех браузерах.В старых браузерах вы можете разделить свою работу, заставив сам скрипт вызываться по таймаутам.Всякий раз, когда происходит тайм-аут, скрипт передает браузеру свои события, после того как браузер завершит работу, ваш следующий тайм-аут будет запущен.1013 *
В примере на jsfiddle закомментирован синхронный вызов, вы можете вернуть его обратно, чтобы браузер начал сканировать.Обратите внимание, что асинхронный вызов занимает много времени, но он не вызывает длительное сообщение сценария и позволяет вам взаимодействовать со страницей во время вычислений (выбор текста, эффекты наведения кнопок).Вы можете увидеть, как он печатает частичные результаты на панели справа внизу.
ОБНОВЛЕНИЕ http://jsfiddle.net/mendesjuan/PucXf/8/
Давайте попробуем использовать функцию задачи c-smile для реализации суммыквадраты.Я думаю, что ему не хватает параметра, функции для обратного вызова, когда задача завершена.Использование task
позволяет нам создавать несколько чанкованных функций без дублирования работы вызова setTimeout и итерации.
/**
* @param {function} worker. It is passed two values, the current array index,
* and the item at that index
* @param {array} list Items to be traversed
* @param {callback} The function to call when iteration is finished;
* @param {number} maxit The number of iterations of the loop to run
* before yielding, defaults to 1000
*/
function task(worker, list, callback, maxit)
{
maxit = maxit || 1000;
var idx = 0;
exec_chunk();
function exec_chunk()
{
for(var n = 0; n < maxit; ++n)
{
if(idx >= list.length) {
callback();
return;
}
worker(idx, list[idx]);
idx++;
}
setTimeout(exec_chunk,1);
}
}
function sumOfSquaresAsync(list, callback)
{
var total = 0;
// The function that does the adding and squaring
function squareAndAdd(index, item) {
total += item * item;
// DOM manipulation to make it take longer and to see progress
var node = document.createElement("div");
node.innerHTML = "Async temp value = " + total;
document.body.appendChild(node);
}
// Let the caller know what the result is when iteration is finished
function onFinish() {
callback(total);
}
task(squareAndAdd, list, onFinish);
}
var list = [];
for (var i = 0; i < 100000; i++) {
list.push(Math.random());
}
sumOfSquaresAsync(list, function(total) {
console.log("Sum of Squares is " + total);
})