2011-09-01 7 views
10

Estoy cargando código (funciones) dinámicamente desde un servidor y ejecutándolo como código JavaScript, luego lo almacena en una matriz y se ejecuta. Todos estos fragmentos de código se deben ejecutar exactamente una vez. El psuedocode sigue como tal¿Hay operaciones atómicas de javascript para tratar con la naturaleza asincrónica de Ajax?

function fetch(foo){ 
    if (foo in fooArray){ 
      //Do Nothing 
    else{ 
      //Fetch foo via Ajax and execute foo() 
    } 
} 

El problema es mucho más complejo, pero en esencia si ejecuta el siguiente comando

fetch('someFunctionName'); 
fetch('someFunctionName'); 
fetch('someFunctionName'); 
fetch('someFunctionName'); 

los cuatro ejecutará la if (foo in fooArray) y asumir que no está en la matriz, y los cuatro procederán a buscar el código y ejecutarlo. Recuerdo que en el día aprendiendo sobre semáforos y mutex, ¿hay cosas para javascript?

+1

Aparentemente es posible, ya que jQuery hace esto: http://stackoverflow.com/questions/7131991/asynchronous-and- synchronous-terms – Mchl

+0

He escrito un blog sobre esto [Por qué no hay una herramienta de simultaneidad en javascript] (http://uzairfarooq.github.io/why-no-concurrency-control-tool-in-javascript/) –

+1

el enlace es roto, debe ser: http://blog.uzairfarooq.com/why-no-concurrency-control-tool-in-javascript –

Respuesta

30

JavaScript es un lenguaje agradable que funciona muy bien con devoluciones de llamada asincrónicas, tiempos de espera, intervalos y eventos de usuario, pero no tiene problemas de simultaneidad. Esto es posible porque JavaScript es esencialmente de un solo subproceso: una pieza determinada de código siempre se ejecuta atómicamente y nunca se interrumpe con otro subproceso que ejecuta JavaScript.

Su función fetch() siempre se ejecutará sin interrupción. Si se ejecuta como parte de la devolución de llamada AJAX y si hay varias devoluciones de llamada AJAX pendientes, se pondrán en cola.

Otro ejemplo: si tiene un controlador de eventos asignado a un elemento de entrada y dispara el evento varias veces a la vez, los controladores de eventos no se ejecutarán simultáneamente. En su lugar, se pondrán en cola y se ejecutarán secuencialmente. Esto también se aplica a eventos múltiples activados por setTimeout()/setInterval().

Como nota al margen: esta es una de las razones por las que node.js es tan robusto: utiliza solo un hilo y nunca bloquea en E/S pero utiliza devoluciones cuando los datos están listos/se produce el evento.

+5

Estrictamente hablando [web workers] (http://en.wikipedia.org/wiki/Web_Workers) Permitir la ejecución concurrente de JS, pero dado que la única interacción entre los trabajadores web y JS "normales" ocurre a través de los mensajes, * todavía * no tiene ningún problema de concurrencia. –

+0

Tomasz Veo lo que dices, gracias. – puk

+0

@Tomasz, si las llamadas AJAX tardan demasiado, tal vez una no quiera tener demasiadas (más de 2 o 6 dependiendo del navegador) pendientes, entonces ofrezco una solución de almacenamiento en caché a continuación ... ¿qué piensas? –

1

Javascript es esencialmente de una sola hebra, por lo que no necesita un mutex. Su ir a buscar podría configurar de tal manera que las banderas posteriores fetch llamadas podrían evitar realizar llamadas ajax, por ejemplo:

var beingFetched = {};//map onflight -> callbacks 
function fetch(foo){ 
    if (foo in fooArray){ 
     //Do Nothing 
    } else { 
     if (beingFetched.foo) { //note empty array is truthy 
      //register a callback 
      var callback = function(r){ 
      //anything you need to do wit the return object r 
      //maybe even eval it. 
      }; 
      //the callback would more likely be an argument to fetch itself 
      //or you could use a promise API instead so that you can at your will 
      //register multiple callbacks - for error, for success etc. 
      beingFetched.foo.push(callback); 
     } else { 
      beingFetched.foo = [];//truthy 
      //Fetch foo via Ajax and execute 
      $.ajax("getFoo/"+foo).done(function() { 
       _.each(beingFetched.foo, function(cb){ 
        cb.apply(cb,arguments); 
       }); 
       delete beingFetched.foo; 
      }); 
     } 
    } 
} 
Cuestiones relacionadas