Domanda

Ho una funzione JavaScript che è abbastanza lungo e svolge una serie di compiti, vorrei relazione all'utente aggiornando il contenuto di un elemento SPAN con un messaggio come vado. Ho provato ad aggiungere document.getElementById ( 'spnProgress'). InnerText = ... dichiarazioni per tutto il codice funzione.

Tuttavia, mentre la funzione è in esecuzione l'interfaccia utente non aggiornerà e in modo che solo mai visto l'ultimo messaggio scritto al SPAN che non è molto utile.

La mia soluzione attuale è quello di rompere il compito in un certo numero di funzioni, al termine di ciascun ho impostato il messaggio SPAN e poi "trigger" il prossimo con una chiamata window.setTimeout con un ritardo molto breve (10ms Say ). Questo controllo i rendimenti e permette al browser di ridipingere lo SPAN con il messaggio aggiornato prima di iniziare la fase successiva.

Tuttavia lo trovo molto disordinato e difficile seguire il codice, sto pensando ci deve essere un modo migliore. Qualcuno ha qualche suggerimento? C'è un modo per forzare lo SPAN ridipingere senza dover lasciare il contesto della funzione?

Grazie

È stato utile?

Soluzione

Il modo in cui si sta facendo è il modo giusto (al momento, la situazione potrebbe cambiare gli standard emergono e vengono adottate [vai di Andrew Aylett risposta ], ma non ancora per un po). Dovete cedere in quel modo per permettere al browser di fare i suoi aggiornamenti dell'interfaccia utente. Ho scoperto che più ci penso in questo modo, le cose più pulite diventano, ma i miei primi colpi a farlo erano effettivamente abbastanza "disordinato". Speriamo che a trovare la stessa cosa che ci si abitua ad esso.

Altri suggerimenti

Se hai il controllo del browser di destinazione, si può essere in grado di utilizzare un HTML5 thread di lavoro per fare il lavoro in background.

È necessario essere consapevoli che in alcuni browser verrà visualizzato un messaggio di timeout dello script se si dispone di uno script di lunga esecuzione. Quindi in realtà è auspicabile dividere questo utilizzando un timer.

Detto questo, se siete alla ricerca di un modo davvero strutturato di fare questo, allora si può guardare in una biblioteca sfondo compito che ho scritto per un progetto di controllo ortografico. Esso consente di implementare Map / Reduce contro matrici di dati su un timer.

https://github.com/jameswestgate/taskjs

E 'come chiedere se è possibile interrompere una procedura senza interrompere una procedura. La risposta è no. Devi usare un setTimeout () o setInterval () per passare il controllo al motore di rendering del browser.

Se si utilizza setInterval () si può ottenere quel processo in corso e nella funzione di eseguire semplicemente aggiornare una variabile esterna, che sarà interrogato dalla funzione chiamata da setInterval (). In questo modo si hanno solo per effettuare una chiamata invece di fare loro in un ciclo.

Non che io sappia. Si potrebbe rompere il codice in modo tale che le singole funzioni possono condividere variabili, così:

var a = some_local_state();
runTasksWithProgress([
    function() {
        do_some_work(a);
        a = a + 1;
    },
    function() {
        do_some_other_work(a);
        a = a * 2;
    },
    ...
    ]);

runTasksWithProgress è un po 'complicato. Si potrebbe fondamentalmente invocare il primo compito, aggiornare lo stato, quindi impostare una richiamata per eseguire le attività successive.

Questo approccio potrebbe alleviare alcuni del dolore.

Una cosa come questa può funzionare se il lavoro della tua funzione viene eseguita in un ciclo. Esso controlla la quantità di tempo che è passato e aggiorna la barra di avanzamento se 1/2 secondo è passato. (L'esempio è non testati. Così potrebbe essere necessario giocare con un po '.)

var start;
function longRunning(lastState){
    start = (new Date);
    for(var i = lastState; i < 1e6 /*= 1000000 iterations */; ++i){
         if((new Date)-start<500){
             // do your stuff;
         }
         else{
             // call a function to update the progress bar
             updateProgressBar();
             // continue the loop...
             setTimeout(function(){longRunning(i);},13);
             break;
         }
    }

}
longRunning(0);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top