Autor: Marijn Haverbeke Fecha: July 24th de 2007
del Esquema de llamadas con corriente de continuación de la función hace posible capturar un cálculo, un estado de la pila de llamadas por así decirlo, y reanudar el mismo estado en un momento posterior. Además de tal primitiva, se pueden implementar varias formas de manejo de excepciones y trucos de Longjmp tipo C.
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);
Esto se puede transformar de la siguiente manera: Añadimos un argumento adicional para cada función, que se utiliza para pasar la continuación de la función. Esta continuación es un valor de función que representa las acciones que deben ocurrir después de que la función 'devuelve'. La pila (llamada) se vuelve obsoleta en el estilo de continuación de paso: cuando una función llama a otra función, eso es lo último que hace. En lugar de esperar que la función llamada regrese, pone cualquier trabajo que quiera hacer después en una continuación, que pasa a la función.
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(){});
Imagine que tenemos un documento original para capitalizar. Simplemente atravesarlo de una vez lleva cinco segundos, y congelar el navegador durante cinco segundos es un estilo bastante malo. Considera esta simple modificación de capitaliseText (no prestar atención a la fea global):
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();
}
Ahora, cada veinte nodos, el cálculo se interrumpe por cien milisegundos para dar la interfaz del navegador un momento para responder a los usuarios entrada. Una forma muy primitiva de enhebrar: incluso puedes ejecutar múltiples cálculos al mismo tiempo de esta manera.
Una aplicación más comúnmente útil de esto está relacionada con XMLHttpRequests, o con los varios hacks de etiquetas IFRAME y SCRIPT utilizados para simularlos. Estos siempre requieren que uno trabaje con algún tipo de mecanismo de devolución de llamada para manejar los datos que el servidor envía de vuelta. En casos simples, funcionará una función trivial, o se pueden usar algunos valores globales para almacenar el estado del cálculo que debe reanudarse después de que los datos vuelvan. En casos complejos, por ejemplo, cuando los datos están siendo utilizados por una función que debe devolver algún valor a su interlocutor, las continuidades simplifican considerablemente las cosas. Simplemente registra la continuación como devolución de llamada, y su cálculo se reanuda cuando la solicitud finaliza.
JavaScript simplemente cautivador? Recomiendo esta lectura a los amantes y enemigos de JS. –
Esta debería ser la respuesta definitiva a esta pregunta. ¡Gracias! ¡Lo hizo todo tan claro! –
Este enlace está muerto, ¡ay! ¿Alguna posibilidad de una nueva ubicación? – Abel