2009-11-02 17 views
50

Aquí es mi tema - Necesito descargar dinámicamente varios scripts usando jQuery.getScript() y ejecutar cierto código JavaScript después se cargaron todos los guiones, así que mi plan era hacer algo como esto:¿Es JavaScript multiproceso?

function GetScripts(scripts, callback) 
{ 
    var len = scripts.length 
    for (var i in scripts) 
    { 
    jQuery.getScript(scripts[i], function() 
    { 
     len --; 
     // executing callback function if this is the last script that loaded 
     if (len == 0) 
     callback() 
    }) 
    } 
} 

Esta voluntad solo funcionan de forma confiable si asumimos que script.onload eventos para cada script de disparo y se ejecutan de forma secuencial y sincrónica, por lo que nunca habrá una situación en la que dos o más de los controladores de eventos pasarán check (len == 0) y ejecutarán callback method .

Así que mi pregunta - es esa suposición correcta y, de no ser así, ¿cuál es la manera de lograr lo que estoy tratando de hacer?

+1

javascript es multiproceso, aquí hay un enlace para ver un ejemplo: http://ajaxian.com/archives/multi-threaded-javascript –

+6

@aforloney - eso no es exactamente correcto. Como dice el ingeniero de Sun citado en el artículo, el ** motor de JavaScript de Rhino ** "permite llamadas al método Java. Así que podemos usar eso para crear envoltorios de guiones para clases de plataforma Java ... podemos crear fácilmente subprocesos en el guión". –

+0

[async.js] (https://github.com/caolan/async) es excelente para ejecutar código después de que todos los scripts, ya sea en paralelo o en secuencia, se completan –

Respuesta

71

No, JavaScript no tiene varios subprocesos. Se basa en eventos y su suposición de que los eventos se disparan secuencialmente (suponiendo que se carguen de forma secuencial) es lo que verá. Su implementación actual parece correcta. Creo que jQuery's .getScript() inyecta una nueva etiqueta <script>, que también debería obligarlos a cargar en el orden correcto.

+0

Básicamente no me importa si se trata del orden de carga , Solo necesito asegurarme de que mi función de devolución de llamada solo se ejecutará cuando se carguen todos los scripts, ya que depende de todos ellos. – Andrey

+8

Esta es probablemente una pregunta embarazosa y simple, pero si JavaScript no tiene múltiples subprocesos, ¿por qué las animaciones de jQuery encadenadas (por ejemplo) parecen suceder simultáneamente en lugar de en secuencia? –

+10

Las actualizaciones de animación se desencadenan por eventos de temporizador que se activan. – Jacob

10

No, todos los navegadores solo le dan un hilo para JavaScript.

+3

+1, aunque podrían hacer lo contrario, pero por los estragos que seguirían. –

33

Actualmente JavaScript no es multiproceso, pero las cosas cambiarán en un futuro próximo. Hay un new thing in HTML5 llamado Worker. Te permite hacer un trabajo en segundo plano.

Pero actualmente no es compatible con todos los navegadores.

+0

Trabajador es algo nuevo en la implementación de Javascript, pero no veo cómo tiene nada que ver con HTML 5 – Andrey

+0

Oh ... sí, mi mal ... no sé de dónde lo saco de –

+5

Web Workers is parte de la especificación de HTML5. http://www.whatwg.org/specs/web-workers/current-work/ – Rob

10

JavaScript no es multiproceso: tiene la garantía de que cualquier controlador que utilice no será interrumpido por otro evento. Cualquier otro evento, como clics del mouse, devuelve XMLHttpRequest y temporizadores se pondrá en cola mientras se ejecuta el código y se ejecutará uno tras otro.

15

El JavaScript (ECMAScript) specification no define ningún mecanismo de subprocesamiento o sincronización.

Además, los motores de JavaScript en nuestros navegadores son deliberadamente de un solo subproceso, en parte porque permitir que más de un subproceso de interfaz de usuario funcionen simultáneamente abriría una enorme lata de gusanos. Entonces su suposición e implementación son correctas.

Como comentario, another commenter alude al hecho de que ningún proveedor intérprete de javascript podría añadir funciones de roscado y de sincronización, o un proveedor podría permitir a los usuarios para implementar esas características a sí mismos, como se describe en este artículo: Multi-threaded JavaScript?

+1

Siempre me impresiona la respuesta que se da a la especificación. PD. (sinceramente, no sarcasmo) –

1

pensé que podría ser interesante para probar esto con un " forzados", la entrega de la escritura demorada ...

  1. añaden dos secuencias de comandos disponibles desde Google
  2. añadió delayjs.php como el segundo elemento de matriz. delayjs.php duerme durante 5 segundos antes de entregar un objeto js vacío.
  3. añadió una devolución de llamada que " verifica" la existencia de los objetos que se esperan de el guión archivos.
  4. añaden algunos comandos js que se ejecutan en la línea después de que los GetScripts() llamar, a "prueba " comandos js secuenciales.

El resultado con la carga del script es el esperado; la devolución de llamada se activa solo después de que se haya cargado la última secuencia de comandos. Lo que me sorprendió fue que los comandos js que siguieron a la llamada GetScripts() se activaron sin la necesidad de esperar a que se cargara la última secuencia de comandos. Yo tenía la impresión de que no hay comandos js serían ejecutados, mientras que el navegador estaba esperando en un script js para cargar ...

var scripts = []; 
scripts.push('http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js'); 
scripts.push('http://localhost/delayjs.php'); 
scripts.push('http://ajax.googleapis.com/ajax/libs/scriptaculous/1.8.3/scriptaculous.js'); 


function logem() { 
    console.log(typeof Prototype); 
    console.log(typeof Scriptaculous); 
    console.log(typeof delayedjs); 
} 

GetScripts(scripts, logem); 

console.log('Try to do something before GetScripts finishes.\n'); 
$('#testdiv').text('test content'); 

<?php 

sleep(5); 
echo 'var delayedjs = {};'; 
+2

Bueno, no te confundas: las secuencias de comandos de descarga del navegador están fuera de la secuencia de comandos de JavaScript, por lo tanto, el programa continúa sin esperar a que se carguen las secuencias de comandos. – Andrey

0

es probable que pueda obtener algún tipo de multithreadedness si crea un número de fotogramas en una Documento HTML, y ejecute un script en cada uno de ellos, cada uno de los cuales llama a una función en el marco principal que debería dar sentido a los resultados de esas funciones.

2

Para ser claros, el navegador implementación JS es no multiproceso.

El lenguaje , JS, puede ser multihilo.

Sin embargo, la pregunta no se aplica aquí.

Lo que aplica es que getScript() es asíncrono (devuelve inmediatamente y se pone en cola), sin embargo, el navegador ejecutará el contenido DOM <script> secuencialmente para que su código JS dependiente los vea cargados secuencialmente. Esta es una función del navegador y no depende del enhebrado JS ni de la llamada a getScript().

Si getScript() recuperara scripts con xmlHTTPRequest, setTimeout(), websockets o cualquier otra llamada asincrónica, entonces no se garantizaría que sus scripts se ejecuten en orden. Sin embargo, su devolución de llamada seguirá recibiéndose después de que se ejecuten todas las secuencias de comandos, ya que el contexto de ejecución de la variable 'len' está en un cierre que persiste en su contexto mediante invocaciones asincrónicas de su función.