Modificando el setTimeout global

14 Abr 2011

El problema

Twitter es una herramienta de trabajo e investigación fantástica. Basta con que surja desde algún rincón un reto para que los desarrolladores comiencen a aportar soluciones originales. Es el desarrollo colaborativo llevado a su máxima expresión.

Por ejemplo, no hace mucho tiempo que comentamos en este mismo blog aquel interesante problema que planteaba la escritura en Javascript de una función para imprimir los primeros 1000 números sin utilizar bucles ni condicionales. En esta ocasión, el reto venía a raíz de un post de Ben Cherry en su Adequately Good, en el que se preguntaba cómo modificar la función nativa setTimeOut en un ámbito global.

La idea era conseguir una forma de configurar un tiempo específico de retardo para cada acción o evento que precisemos: algo aparentemente fácil pero que conlleva muchos problemas en un entorno real multinavegador.

La evolución de esta idea fue el crear una función independiente que, mediante los argumentos, actúe aplicando ese retardo personalizado a cualquier acción o efecto que nos interese.

La solución

Tras varias pruebas del propio Ben Cherry (@bcherry) y las aportaciones de @kangax, @cowboy y @angusTweets, se llegó a una solución multinavegador que conseguía alterar el comportamiento del setTimeout con el menor impacto colateral posible. El código y su análisis lo tenéis íntegro aquí.

Sin embargo, se pretendió ir más lejos: crear una función lanzadera de cualquier otra con parámetros personalizados. Con esto, no solo se podía establecer un tiempo (delay) para cada evento o acción, sino que permite modificar cualquier otro proceso interno a voluntad.

El código es el siguiente:

function kall( fn, context /*, args*/ ) {
  var fnArgs = [].slice.call( arguments, 2 );
  kall.apply.call( fn, context, fnArgs );
}
 
//Examples (tested on IE8, FF, Chrome)...
 
var myFn = function() { alert("Hello") };
var stash = { setTimeout: setTimeout };
 
kall( stash.setTimeout, window, myFn, 2000 ); // alerts "Hello" after 2 seconds
kall( console.log, console, "Hello World" ); // Hello World

Con esto, creamos una nueva función, kall (a la espera de un nombre mejor) que recibe a otra como parámetro, un contexto y los argumentos pertinentes que se quieren aplicar.

En la primera llamada comprobamos cómo funciona correctamente con los tiempos (delays) mientras que, en la segunda, enviamos un mensaje a la consola.

Resolvemos así el problema inicial del setTimeout a la vez que ampliamos las posibilidades gracias a un patrón más flexible y elegante.

Más:

Solo un marciano comentando!

  1. Uziel

    Hola, interesante artículo… pero perdona mi ignorancia =$ … esto de retrasar 2 segundos las funciones como para que serviría ??? o por puro gusto salió ???

    Gracias de antemano.
    Saludos!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *