2011-09-26 14 views
6

Ho una classe, ChatRoom, che può eseguire il rendering solo dopo aver ricevuto una richiesta HTTP di lunga durata (potrebbe richiedere 1 secondo o 30 secondi). Quindi ho bisogno di ritardare il rendering fino al ChatRoom.json non è nullo.Ritarda in modo asincrono JS finché non viene soddisfatta una condizione

Nel codice seguente, sto usandodella libreria di chiusura. Funziona, ma c'è un modo migliore (forse senza bisogno di chiudere la libreria) per fare questo?

ChatRoom.prototype.json = null; // received after a long-running HTTP request. 

ChatRoom.prototype.render = function() { 
    var thisChatRoom = this; 

    function onReady() { 
     console.log("Received JSON", thisChatRoom.json); 
     // Do rendering... 
    } 

    function onFailure() { 
     alert('Sorry, an error occurred. The chat room couldn\'t open'); 
    } 

    function isReady() { 
     if (thisChatRoom.json != null) { 
      return true; 
     } 
     console.log("Waiting for chat room JSON..."); 
     return false; 
    } 

    // If there is a JSON request in progress, wait until it completes. 
    if (isReady()) { 
     onReady(); 
    } else { 
     var delay = new goog.async.ConditionalDelay(isReady); 
     delay.onSuccess = onReady; 
     delay.onFailure = onFailure; 
     delay.start(500, 5000); 
    } 
} 

nota che "mentre (json == null) {}" non è possibile perché sarebbe sincrono (bloccando ogni altra esecuzione JS).

+2

Perché non si utilizza la richiamata dalla richiesta HTTP? – SLaks

+0

Non riesco a utilizzare quella richiamata perché il rendering potrebbe essere chiamato prima che venga restituito JSON o 10 minuti dopo che è stato restituito. Fondamentalmente, voglio essere in grado di chiamare render() in qualsiasi momento nel tempo che voglio. –

+1

È ancora possibile utilizzare il callback. In 'render', controlla se il JSON è stato restituito e, in caso contrario, aggiungi a un array di callback. O semplicemente usa i nuovi oggetti Deferred di jQuery, che fa questo per te. – SLaks

risposta

20

Considerate questo:

(function wait() { 
    if (chatroom.json) { 
     chatroom.render(); 
    } else { 
     setTimeout(wait, 500); 
    } 
})(); 

Questo controllerà ogni mezzo secondo.

Demo online:http://jsfiddle.net/kBgTx/

-1

La risposta mi è venuta è come questo:

var count = 0; 
// Number of functions that need to run. This can be dynamically generated 
// In this case I call check(data, cb) a total of 3 times 
var functionNum = 3; 
function toCallAfter(){ 
    console.log('I am a delayed function'); 
} 

ho avuto questo per una funzione di controllo che correva una volta regolarmente e due volte in un ciclo:

check(data, function(err){ // check is my asynchronous function to check data integrity 
    if (err){ 
     return cb(null, { // cb() is the return function for the containing function 
      errCode: 'MISSINGINFO', 
      statusCode: 403, 
      message : 'All mandatory fields must be filled in' 
     }); 
    } // This part here is an implicit else 
    count++; // Increment count each time required functions complete to 
      // keep track of how many function have completed 
    if (count === functionNum) { 
     return anon(); 
    } 
    return; 
}); 
// Run twice more in a loop 
for(var i = 0; i < 2; i++) { 
    check(data, function(err) { // calls check again in a loop 
     if (err){ 
      return cb(null, { 
       errCode: 'MISSINGINFO', 
       statusCode: 403, 
       message : 'All mandatory fields must be filled in' 
      }); 
     } 
     count++; 
     if (count === functionNum) { 
      return toCallAfter(); 
     } 
     return; 
    }); 
} 

Infine, vorrei segnalare un errore di prestazioni significativo nella risposta alternativa (e straordinariamente comune) er:

(function wait() { 
    if (chatroom.json) { 
     chatroom.render(); 
    } else { 
     setTimeout(wait, 500); 
    } 
})(); 

In questo caso, si sono essenzialmente tenendo il browser o il server (se si utilizza node.js) in ostaggio per 500 millisecondi per ogni controllo, che è un tempo incredibilmente lungo per un computer. Significa un enorme successo in termini di prestazioni. La mia soluzione di tenere traccia delle funzioni completate richieste è libera da vincoli temporali e funzionerà immediatamente non appena tutte le funzioni saranno completate.

+0

500 millisecondi sono una vita sì, ma tenendo in ostaggio il thread JS non lo sei. Le funzioni asincrone in javascript non sono thread-blocking, ma sono in coda per l'esecuzione in futuro. La risposta accettata è comune perché è un javascript idiomatico ed è il più performante possibile quando non si dispone di un evento "pronto" a cui è possibile rispondere. –

Problemi correlati