Newsgroup: it.comp.lang.javascript
Titolo: Codice che sbanda ad alta velocità

Ho il codice sotto, in ff23b, che con tm=1 non ritorna bene il 
riferimento al documento. Quando vado a riprendere dei value dal form mi 
ritorna dei dati di una finestra adiacente. Questo mi succede in 
rapporto alla grandezza della variabile tm. A dire il vero anche con 
tm=1200 qualche volta mi succede ma molto di radon in confronto con tm=1.
Da cosa dipende? Posso trovare un rimedio?
 
;b=windows lists....
var tm=1200;
for(i=0;i<b.length;i++){
setTimeout(function(ww, i,t){
ti.wind[i]=window.open(ww.href,t);
}, tm*i, b[i],i,"titolo"+i);
}

 }
 
Non ho idea a cosa ti serva tale codice, ma io non scriverei una cosa
del genere manco sotto tortura: i `setTimeout` andrebbero usati col
contagocce, e qui praticamente lo usi all'interno di un loop.
 
Evitiamo il codice nello specifico – intendo la funzione invocata dal
timeout – in quanto già con lo shadowing di `i` non è ben chiara, in piú
ignoro tutto il contesto (`ti.wind` etc); quello che vuoi fare qui sembra:
 
- Per ogni elemento dell'array, invocare del codice ogni msec * indice
dell'array.
 
In questo modo, ad esempio, se `msec` è 1200 come sopra, tu avrai `0`,
`1200`, e `2400` con un array di tre elementi.
 
Ora, è sbagliato fare una cosa del genere per due motivi: primo,
`setTimeout` non può essere invocato con un msec inferiore a 4,
qualsiasi altro numero probabilmente ricadrà sotto tale limite (vedasi
https://developer.mozilla.org/en-US/docs/Web/API/window.setTimeout#Minimum.2F_maximum_delay_and_timeout_nesting
);
conta che prima era 10ms: il motivo per cui hai quell'errore di cui
sopra, probabilmente è dovuto alla cattiva logica di programmazione del
tuo codice sommata al limite del timeout. Se hai bisogno di un timeout
di 0 msec, segui i consigli del sopracitato link.
 
Il secondo motivo per cui è sbagliato è che non dovresti mai schedulare
timeout sequenziali contemporaneamente – a meno di specifiche ragioni –
e men che meno in un ciclo.
Anche perché non è garantito da nessuna parte che i tre timeout verranno
eseguiti a distanza di 1200 msec, se l'engine o la macchina è occupata a
fare altro, è probabile che possano venire eseguiti contemporaneamente.
Ciò che dovresti fare, quindi, è schedularne uno dopo l'altro:
 
    function foo(b, i, t) {
        // ammesso ciò sia corretto
        ti.wind[i] = window.open(b[i].href, t);
 
        if (++i < b.length)
            setTimeout(foo, 1200, b, i, "titolo" + i);
    }
 
    foo(b, 0, "titolo0");
 
Questo è un approccio piú corretto perché schedula il timeout solo
quando il precedente è terminato, quindi è impossibile che si accavalli.
In questo modo puoi anche usare msec piú bassi – sempre con i limiti di
cui sopra.
 
Ripeto comunque, che generalmente questo approccio è sconsigliatissimo:
non si usano timeout in questo modo se non c'è una ragione piú che
valida. In generale, ascoltare il giusto evento o notifica (dato che sei
su firefox) è una strada decisamente migliore.

Il codice dovrebbe caricare una serie di pagine.
Ogni pagina è memorizzata nell'array wind.
Poi faccio un ciclo in wind e copia in una variabile una serie di input 
dentro document.
In origine non avevo usato timeout solo che successivamente mi sono 
accorto del bug. Praticamente non sempre gli input corrispondevano alle 
pagine ma ogni tanto sfavano nelle pagine adiacenti. Ho rattoppato 
creando un delay col timeout ma ancora anche se molto di rado si 
verifica il problema.
Ora potrei provare la tua function foo, ma così tornerei all'origine:
 
;b=windows lists....
var tm=1200;
for(i=0;i<b.length;i++){
ti.wind[i]=window.open(ww.href,t);
}
 
giusto? ma allora da cosa può dipendere quel problema di sfasatura?
 

 giusto?
 
No. In questo caso non hai delay, esegui tutto nello stesso tick, mentre
con il codice che ti ho dato usi un timeout, e quindi non è la stessa cosa.
 
Comunque anche se funzionasse sarebbe solo un rattoppare un sintomo, piú
che curare il male. Andrebbe visto il problema effettivo.

      foo(b, 0, "titolo0");
...e usare setInterval invece di setTimeout?
Massi

 ...e usare setInterval invece di setTimeout?
 
Ti toccherebbe usare variabili esterne per poter iterare l'array in tal
caso, cosa che con il `setTimeout` non hai bisogno; rimane tutto
all'interno dello scope. Inoltre, dipendentemente dall'implementazione
del browser e sistema operativo, potresti comunque avere un
accavallamento di esecuzione codice, cosa che invece in questo caso
sicuramente non accade, giacché la "schedulatura" avviene nella funzione
stessa.
 
Detto questo, personalmente preferisco sempre i timeout agli interval:
sono piú flessibili.
 

 sono piú flessibili.
Ammetto di averla "buttata lì" senza aver prima letto per bene il codice 
(al momento ne ho fin sopra le orecchie di quello di altri che devo 
rivisitare ;) ).
Concordo con ciò che hai detto (alla fine un Interval è come una serie 
di Timeout), ma rabbrividisco in entrambi i casi: il timeout, almeno, 
quando scade è un pensiero in meno ;)
Massi