2010-06-28 20 views
14

Supponiamo di voler bloccare l'esecuzione di Javascript per un certo periodo di tempo per qualche strano motivo, come posso farlo. Non c'è sonno() in JS. Pls non dice do while while() perché non va bene. Posso fare un window.showModalDialog e mettere una window.close nella finestra di dialogo modale con setTimeout di pochissimo tempo in modo che l'utente non noti la finestra di dialogo. Questo sarà come dormire per un breve periodo di tempo e posso chiamarlo più volte se necessario. C'è un altro modo?sleep() in Javascript

Per elaborare, il mio caso d'uso è che il database SQL5 HTML ha fornito aspi asincroni ma voglio usarlo per una webapp samll per la quale lo store non sarà mai grande. Quindi non c'è bisogno di un aspi asincrono perché le query sul piccolo negozio verranno eseguite sul lato client. Quindi voglio scrivere un ORM con sync api in modo che gli sviluppatori possano usarlo più facilmente. Per colmare questo asincrono per sincronizzare API, ho bisogno di qualcosa come il sonno.

+1

Puoi esporre un po 'il tuo esempio? Sembra un 'setInterval()' è ciò che stai cercando, ma non sono al 100% chiaro sul tuo caso d'uso. –

risposta

13

window.setTimeout o window.setInterval sono praticamente i tuoi unici amici.

Un esempio di come utilizzare setTimeout per chiamare in modo ricorsivo una funzione che imposta un altro timeout è la seguente

function go() { 
    if (go.count < 4) { 
     // logs 1, 2, 3 to firebug console at 1 second intervals 
     console.log(go.count++); 
     window.setTimeout(go, 1000); 
    } 
} 
go.count = 1; 

go(); 

Si può scegliere di catturare l'timeoutID da usare con window.clearTimeout se è necessario cancellare il timeout prima sta finendo.

Nota che né window.setTimeoutwindow.setInterval esecuzione di blocco di altro script - Non credo che questo sia possibile con JavaScript nel suo aspetto attuale. Ci sono modi che potrebbero essere codificati per simulare il blocco dell'interfaccia utente, come l'uso di showModalDialog o di avere un valore globale di blocking booleano che sono il più vicino possibile.

+4

Questo è già nella domanda :) –

+1

-1: è già nella domanda. E CHI ha messo su questo? – naiad

+1

true, è nella domanda ma è praticamente la risposta JavaScript a 'Thread.Sleep()'/'Inserisci linguaggio equivalente'. –

9

@Russ Cam è corretto, setTimeout è quello che stai cercando. Il modo in cui l'hai menzionato nella domanda, però, mi fa pensare che ci possa essere una certa confusione su come viene usata.

Non bloccherà l'esecuzione del blocco in cui si trova, ma chiamerà la sua funzione di input dopo un certo intervallo. A titolo di esempio:

function illustration() { 
    // start out doing some setup code 
    alert("This part will run first"); 

    // set up some code to be executed later, in 5 seconds (5000 milliseconds): 
    setTimeout(function() { 
    alert("This code will run last, after a 5 second delay") 
    }, 5000); 

    // This code will run after the timeout is set, but before its supplied function runs: 
    alert("This will be the second of 3 alert messages to display"); 
} 

Vedrete tre messaggi di avviso quando si esegue questa funzione, con un ritardo tra la seconda e la terza:

  1. "Questa parte verrà eseguito prima"
  2. "Questo sarà il secondo di 3 messaggi di avviso per visualizzare"
  3. 'Questo codice verrà eseguito scorso, dopo un ritardo di 5 secondi'
+0

Sì, lo capisco, ma voglio bloccare l'esecuzione così, setTimeout non aiuta. – nomind

+1

Se si desidera bloccare l'esecuzione, allora 'while' è ciò che si desidera, ma ciò bloccherà il browser (perché sta bloccando l'esecuzione). Dubito che tu voglia davvero bloccare l'esecuzione. – pkaeding

3

Questa risposta può essere un po 'fastidiosa ma nuda con esso :-).

Poiché javascript è in genere eseguito all'interno di un browser, che è multithreading di cui javascript può occupare più thread, non esiste il concetto di "sleep globale" come in un programma con thread singolo.

Se si desidera sospendere un'operazione in un modo ragionevole, è possibile prendere in considerazione quanto segue.

Diciamo che si desidera il seguente

function foo(s) { 
    var j = 1; var k = 1; 
    sleep(s); // This would be nice right? 
    window.alert("Sum is : " + (j+k)); 
} 

diventa realtà:

function foo(s) { 
    var j = 1 ; var k = 1; 
    setTimeout(s, function() { 
      window.alert("Sum is : " + (j+k)); 
    }); 
} 

Naturalmente il problema è che in un certo senso procedurale si consiglia di avere qualcosa di simile

function foo() { 
    do stuff; 
    pause(); 
    do more stuff; 
    return; 
} 

function bar() { 
     foo(10); 
     window.alert("I want this to happen only after foo()"); 
} 

Il problema è che non è possibile farlo utilizzando setTimeout, come mostrato sopra

Tuttavia è possibile fare qualcosa di simile:

function foo(s, afterwards, afterparms) { 
    var j = 1 ; var k = 1; 
    setTimeout(s, function() { 
      window.alert("Sum is : " + (j+k)); 
      afterparms.parm1 = afterparms.parm1.toUpperCase(); 
      afterwards(afterparms); 
    }); 
} 

function bar() { 
     foo(10, function() { 
      window.alert("This will happen after window.alert"); 
     }, { parm1: 'hello', parm2: 'world' }); 
} 

prega di notare che di cui sopra è solo un modo per andare a passare informazioni alle funzioni, si possono fare delle cose davvero interessanti se si guarda fino convenzioni funzione di chiamata, argomenti variabili e tali

Questo è fastidioso da programmare se si pensa proceduralmente. Tuttavia, ci sono due cose da ricordare per quanto riguarda javascript. NON è un linguaggio procedurale, NOR è un linguaggio orientato agli oggetti. Javascript è un linguaggio funzionale con un sofisticato modello di gestione degli eventi. Quindi devi pensare in questi termini.

Ha senso anche, dal momento che la tipica macchina javascript è un gui (browser Web) che dal design non si vuole bloccare completamente durante il tentativo di elaborare qualcosa. Immagina che il tuo browser si blocchi completamente mentre una pagina sta facendo qualcosa, vorresti strangolare il programmatore che ti fa questo.

Il codice Javascript dovrebbe essere di natura "fire-and-forget" e se le cose devono attendere che si verifichi un evento prima di procedere, si dovrebbe guardare il modello di eventi javascript.

Mentre questa è una programmazione sconveniente quando si vuole fare qualcosa di banale, è probabile che si stia usando la pausa per aspettare in un modo che potrebbe imbattersi in condizioni di gara per cominciare, e che c'è un modo più appropriato per "effetto" che stai cercando di raggiungere.

Se pubblichi il tuo caso PARTICOLAR, potrebbero esserci ulteriori informazioni su come affrontare una situazione del genere.

Cheers,

+0

Sbagliato. JS NON esegue multithreading. setTimeout inoltre non fa quello che la domanda richiede. Vedi la mia risposta per i dettagli. – selfawaresoup

+0

JavaScript IS a thread singolo. E lo sono anche molti browser. –

+0

Apprezzo tutti i tuoi commenti. Ho aggiornato la domanda con il mio caso d'uso, se ciò giustifica la necessità di dormire(). – nomind

3

posso fare un window.showModalDialog e mettere un window.close nella finestra di dialogo modale con setTimeout di tempo molto piccolo

Questo è inventiva, ma consente solo per l'utente interazione con qualsiasi cosa nella finestra di dialogo modale, per il periodo di tempo in cui è aperta. Il resto del browser rimane bloccato come se avessi appena chiamato un brutale ciclo while (new Date().getTime()<t1);.

La finestra di dialogo modale è più gentile sui cicli della CPU e eviterà di attivare il watchdog del tempo di esecuzione dello script in caso di attese più lunghe, ma dovresti bilanciarlo contro il fastidio di una finestra di dialogo di apertura lampeggiante che distrae, e il supporto browser non universale, e il problema di chi odia i dialoghi modali!

Questo sarà come dormire per un breve periodo di tempo e posso chiamarlo più volte se necessario. C'è un altro modo?

Cosa stai cercando di ottenere dormendo? Senza tornare al ciclo degli eventi o attivare una finestra di dialogo modale, non avrai alcun aggiornamento sullo schermo o interazione con l'utente, quindi non vedo cosa farà un sonno in linea per te. Certamente non puoi fare animazione in questo modo.

In Firefox si ottiene in stile Python generators, che consente di scrivere un processo di interazione in stile procedurale utilizzando yield per restituire il controllo al browser in base alle esigenze. Ciò può migliorare la semplicità del codice in quanto non è necessario riscrivere le strutture condizionali e in loop come stato memorizzato nelle variabili. Tuttavia, poiché solo i browser Mozilla lo supportano, non è possibile utilizzarlo in natura per il prossimo futuro.

ETA:

voglio scrivere un ORM con API di sincronizzazione in modo che gli sviluppatori possono utilizzare più facilmente. Per colmare questo asincrono per sincronizzare API, ho bisogno di qualcosa come il sonno.

Spiacente, non può essere fatto nel caso generale. JavaScript di base non ha thread, co-routines o altre primitive in grado di collegare la sincronizzazione e il codice asincrono.

Le specifiche del database SQL Web si basano sui browser che richiamano la funzione di gestione dei risultati (passata a executeSql()) come richiamata del browser. I callback del browser possono essere attivati ​​solo quando il controllo è passato al browser, non all'interno di un thread sincrono di esecuzione.

In teoria, si potrebbe aprire un modalDialog, fare la asincrona Web SQL Database chiamata all'interno finestra s' il modalDialog, e hanno il modalDialog tornare il risultato in codice sincrono negli script della finestra chiamante. Tuttavia, al momento non esiste un browser che supporti sia openDatabaseeopenModalDialog!

+0

Vedere il caso d'uso nella domanda aggiornata, se ciò giustifica la necessità. Ma ci sono problemi con il mio approccio showModalDialog come se chiudessi, diciamo entro 10 ms, potrebbe apparire su macchine lente (è possibile?) E l'attenzione non tornerà nella posizione corretta nella finestra genitore. – nomind

+0

@nomind: aggiunta di informazioni inutili. Forse se i futuri browser implementassero insieme sia i dialoghi modali che SQL, potrebbe essere fattibile, ma oltre ai problemi di visualizzazione della finestra, richiederebbe agli utenti di disabilitare i loro blocchi pop-up. Penso che dovrai vivere con il codice asincrono e le funzioni di callback. O semplicemente usa il back-end 'localStorage' sincrono più ampiamente supportato invece di esatto' openDatabase': per una 'piccola webapp' con accesso a stile oggetto, le caratteristiche di un database relazionale non ti aiuteranno affatto. – bobince

+0

Non sono d'accordo. Qualsiasi browser basato su webkit come google chrome ha sia showModalDialog che openDatabase – nomind

6

Per chiarire: la domanda è di arrestare l'esecuzione dello script completamente per un certo periodo di tempo, per non ritardare l'esecuzione di qualche parte di codice, che deve essere un'attività per setTimeout o setInterval.

Un'implementazione pulita di sleep() non è possibile e anche non desiderabile in JavaScript.

setTimout e setInterval NON arrestano l'esecuzione dello script come alcune persone qui sembrano top think. Basta registrare una funzione da eseguire posticipata. Il resto dello script continuerà a essere eseguito mentre il timeout/intervallo è in attesa.

A causa della natura asincrona di JavaScript, l'unico modo per "bloccare" l'esecuzione di un codice sarebbe il ciclo molto brutto e ASSOLUTAMENTE NON RACCOMANDATO durante un determinato periodo di tempo. Poiché JavaScript stesso viene eseguito in un singolo thread (non stiamo parlando di API WebWorkers qui ...). Ciò impedirebbe l'esecuzione di qualsiasi codice JS fino al termine del ciclo. Ma quello è davvero cattivo stile ...

Se il tuo programma non può funzionare senza qualcosa come sleep(), forse dovresti ripensare al tuo approccio.

1

So che questa domanda è un po 'vecchia, ma avevo un problema simile in cui avevo bisogno di simulare uno script che impiegava molto tempo per caricare sulla pagina. Ho risolto il problema creando un endpoint lato server che ha atteso 5 secondi prima di inviare la risposta, quindi ho aggiunto un tag script al DOM per puntare a questo.

Concesso richiede un'implementazione lato server, tuttavia, consente di interrompere la pagina in qualsiasi punto specifico. Come altri hanno già detto, questo bloccherà l'intero browser, non solo il tuo script.