Посмотрите, я нашел это лучшее описание на эту тему.
Автор: Marijn Haverbeke Дата: 24 июля 2007
Схема Позвони-с-тока продолжения функции позволяет захватить вычисления, состояние стека вызовов как бы и возобновить это же состояние позднее. В дополнение к такому примитиву могут быть реализованы различные формы обработки исключений и трюки типа «С».
function traverseDocument(node, func) {
func(node);
var children = node.childNodes;
for (var i = 0; i < children.length; i++)
traverseDocument(children[i], func);
}
function capitaliseText(node) {
if (node.nodeType == 3) // A text node
node.nodeValue = node.nodeValue.toUpperCase();
}
traverseDocument(document.body, capitaliseText);
Это можно преобразовать следующим образом: Мы добавляем дополнительный аргумент для каждой функции, которая будет использоваться для передачи продолжения функции. Это продолжение представляет собой значение функции, представляющее действия, которые должны выполняться после того, как функция «возвращает». Стек (call) становится устаревшим в стиле продолжения - когда функция вызывает другую функцию, это последнее, что она делает. Вместо того, чтобы ждать, пока вызываемая функция вернется, она помещает любую работу, которую он хочет сделать потом, в продолжение, которое она передает функции.
function traverseDocument(node, func, c) {
var children = node.childNodes;
function handleChildren(i, c) {
if (i < children.length)
traverseDocument(children[i], func,
function(){handleChildren(i + 1, c);});
else
c();
}
return func(node, function(){handleChildren(0, c);});
}
function capitaliseText(node, c) {
if (node.nodeType == 3)
node.nodeValue = node.nodeValue.toUpperCase();
c();
}
traverseDocument(document.body, capitaliseText, function(){});
Представьте, что у нас есть документ huuuuge, который можно использовать. Простое перемещение за один раз занимает пять секунд, а замораживание браузера в течение пяти секунд - довольно плохой стиль. Рассмотрим эту простую модификацию capitaliseText (не обращают внимание на безобразное глобальный):
var nodeCounter = 0;
function capitaliseText(node, c) {
if (node.nodeType == 3)
node.nodeValue = node.nodeValue.toUpperCase();
nodeCounter++;
if (nodeCounter % 20 == 0)
setTimeout(c, 100);
else
c();
}
Теперь каждые двадцать узлов, вычисление прерывается в течение сотен миллисекунд, чтобы дать интерфейс браузера момент, чтобы ответить на пользователя вход. Очень примитивная форма потоковой обработки - вы можете одновременно запускать несколько вычислений так же, как это.
Более часто используемое приложение относится к XMLHttpRequests или различным хакам IFRAME и SCRIPT, которые имитируются. Для этого всегда требуется работать с каким-то механизмом обратного вызова для обработки данных, которые сервер отправляет обратно. В простых случаях будет выполняться тривиальная функция или можно использовать несколько глобалов для хранения состояния вычисления, которое должно быть возобновлено после возвращения данных. С сложными случаями, например, когда данные используются функцией, которая должна вернуть некоторое значение своему вызывающему, продолжение значительно упрощает ситуацию. Вы просто регистрируете продолжение как обратный вызов, и ваши вычисления возобновляются, когда запрос заканчивается.
JavaScript просто увлекательный? Я настоятельно рекомендую это прочитать как любителям JS, так и ненавистникам. –
Это должен быть окончательный ответ на этот вопрос. Спасибо! Это сделало все настолько ясным! –
Эта ссылка мертва, увы. Есть ли шанс на новое место? – Abel