È necessario attendere che l'immagine sia caricata (o completata, se memorizzata nella cache). Questo si tradurrà in un'operazione di callback asincrona:
// pure JS:
var img = new Image();
img.src = myDataString;
if (img.complete) { // was cached
alert('img-width: '+img.width);
}
else { // wait for decoding
img.onload = function() {
alert('img-width: '+img.width);
}
}
Nota: Una volta ho avuto lo stesso problema con un progetto che utilizza jQuery. jQuery non fornisce un accesso all'immagine direttamente abbastanza subito dopo averla creata. Sembra, non è possibile essere fatto, ma in puro JS. Ma potresti provare un timeout-loop e aspettare che la larghezza dell'immagine abbia un valore (e rilevare eventuali errori di caricamento/decodifica).
[Edit, vedere i commenti anche] Perché questo funziona (il motivo per cui non v'è alcuna gara-condizione):
JS è single-threaded, nel senso c'è solo una parte del codice eseguito in un dato momento. Tutti gli eventi verranno messi in coda fino all'uscita dall'ambito corrente e verranno attivati solo in quel momento. Grazie a late-binding, tutti gli ascoltatori verranno valutati solo successivamente (dopo che l'ambito corrente è stato eseguito). Quindi il gestore sarà presente e in ascolto non appena viene attivato l'evento onload, indipendentemente dal fatto che il listener sia stato configurato prima o dopo aver impostato l'attributo src. Al contrario, il flag completo viene impostato non appena viene impostato l'attributo src.
Hai aspettato il caricamento dell'immagine? – Musa
@Musa, non credo, guarda la mia modifica – Alon