2010-02-17 20 views
5

Ich brauche so etwas wie dies zu tun:Javascript Block Skriptausführung

  • Führen Sie ein Stück Code
  • Starten Sie ein Bild zu laden und blockieren die Skriptausführung
  • Wenn das Bild wieder aufnehmen, die Ausführung geladen wird
  • Führen Sie den Rest des Codes

ich weiß, dass der einfachste Weg ist es, eine Funktion auf dem onload-Ereignis des Bildes a zuweisen nd dann führe den Rest des Codes in der Funktion aus, aber wenn es möglich ist, möchte ich ein "lineares" Verhalten haben, das die Ausführung des Skripts blockiert und dann wieder aufnimmt. Also, gibt es eine Cross-Browser-Möglichkeit, dies zu tun?

Antwort

3

Der einzige Weg, die Skriptausführung zu blockieren ist eine Schleife zu verwenden, die auch die meisten Browser sperren wird und verhindern jede Interaktion mit Ihrer Webseite.

Firefox, Chrome, Safari, Opera und IE Alle unterstützen die complete Eigenschaft, die schließlich in HTML5 standardisiert wurde. Dies bedeutet, dass Sie eine while-Schleife verwenden können, um die Ausführung des Skripts anzuhalten, bis das Bild vollständig heruntergeladen wurde.

var img = new Image(); 
img.src = "/myImage.jpg"; 
document.body.appendChild(img); 
while (!img.complete) 
{ 
    // do nothing... 
} 

// script continues after image load 

Das gesagt, ich denke, Sie sollten Wege suchen, um Ihr Ziel zu erreichen, ohne den Browser zu sperren.

+0

Ich stimme zu, dass dies ein schlechter Weg ist, aber ich denke auch, dass es der einzige Weg ist. Vielleicht kann ich dem Benutzer die Möglichkeit geben, zwischen dem Blockieren der Skriptausführung und dem Aufruf der Ladefunktion zu wählen, wenn das Bild geladen wird. – mck89

+0

@ mck89: Ich finde es schwer zu glauben, dass es der einzige Weg ist. Ich kann ehrlich sagen, dass ich nie auf eine Situation in JavaScript gestoßen bin, die das Sperren des Skripts erfordert; Es gibt immer einen Weg (z. B. temporäres Überschreiben von Funktionen), um Dinge asynchron zu tun. Sie haben schließlich die Kontrolle über das Skript auf Ihrer Seite. Vielleicht könnten Sie eine weitere Frage zu Ihrem Problem stellen? –

+0

@ mck89: Die Eigenschaft 'complete' existiert für Gecko und IE und könnte auch in anderen Browsern funktionieren. Wenn Sie darauf bestehen, die Ausführung von Skripten zu blockieren, sehen Sie sich mein Update an. –

1

Wenn Sie nichts dagegen haben, einen Vorverarbeitungsschritt haben, versuchen Narrative Javascript, die Sie

können
image.onload = new EventNotifier(); 
image.onload.wait->(); 
+0

Das ist ein großartiges Projekt, aber ich versuche eine einfache Anwendung in reinem Javascript zu erstellen ... und ich weiß nichts über Java :) – mck89

+0

@ mck89: Nach der Vorverarbeitung bekommst du pures Javascript. – kennytm

+0

Ja, ich weiß, aber ich bevorzuge nur Javascript – mck89

1

Dieser Vorschlag ist nicht genau das, wonach Sie gefragt haben, aber ich biete es als eine mögliche Alternative an.

Erstellen Sie eine CSS-Klasse mit dem Hintergrundbild, das Sie verwenden möchten. Wenn Ihre App gestartet wird, weisen Sie diese CSS-Klasse einem DIV zu, der entweder außerhalb des Standorts oder auf Null von null Pixeln verkleinert ist. Dadurch wird sichergestellt, dass das Image vom Server geladen wird. Wenn Sie das Bild laden möchten (Schritt zwei oben), verwenden Sie die von Ihnen erstellte CSS-Klasse. Das wird schnell passieren. Vielleicht schnell genug, dass Sie die nachfolgende Codeausführung nicht blockieren müssen?

+0

Ja, das könnte eine gute Vorlademethode für Bilder sein, aber ich lade das Bild nicht zu Beginn der Anwendung. – mck89

+0

Ich verstehe, aber wenn Sie eine CSS-Klasse mit einem Hintergrundbild-Attribut erstellt, diese Klasse zu einem Dummy-DIV zugewiesen, würden Sie das Bild am Anfang der Anwendung laden. – Upperstage

1

Ich würde nicht versuchen, die Skriptausführung vollständig zu blockieren, da dies den Browser verlangsamen oder den Benutzer sogar warnen könnte, dass die Ausführung eines Skripts zu lange dauert.

Sie können Ihren Code "linearisieren", indem Sie Ereignisse verwenden, um die Arbeit zu beenden. Sie müssen der Funktion ein Timeout hinzufügen, da das Bild möglicherweise nie geladen wird.

Beispiel:

var _img = null; 
var _imgDelay = 0; 
var _finished = false; 

function startWork(){ 
    _img = document.createElement('img'); 
    _img.onload = onImgLoaded; 
    _img.src = 'yourimg.png'; 

    // append img tag to parent element here 

    // this is a time out function in case the img never loads, 
    // or the onload event never fires (which can happen in some browsers) 
    imgTimeout(); 
} 

function imgTimeout(){ 
    if (_img.complete){ 
     // img is really done loading 
     finishWork(); 
    } 
    else{ 
     // calls recursively waiting for the img to load 
     // increasing the wait time with each call, up to 12s 
     _imgDelay += 3000; 

     if (_imgDelay <= 12000){ // waits up to 30 seconds 
     setTimeout(imgTimeout, _imgDelay); 
     } 
     else{ 
     // img never loaded, recover here. 
     } 
    } 
} 

function onImgLoaded(){ 
    finishWork(); 
} 

function finishWork(){ 
    if (!_finished){ 
     // continue here 
     _finished = true; 
    } 
} 
+0

Sind Sie sicher, dass Sie die Ausführung mit setTimeout stoppen können? – mck89

+0

Dies stoppt die Ausführung des Codes nicht, es erlaubt Ihnen zu warten, bis das Image fertig geladen ist, bevor Sie weitere Arbeit machen. Sie hören auf, Ihre eigene Codeausführung auszuführen, indem Sie Ihren verbleibenden Code in die finishWork-Funktion verschieben. – FlashXSFX

1

Sie können xmlhttprequest verwenden und synchronen Modus verwenden.

var url = "image.php?sleep=3"; 
var img = new Image; 
var sjax = new XMLHttpRequest(); 
img.src = url; 
sjax.open("GET", url, false); 
sjax.send(null); 
alert(img.complete); 

Der Trick hier ist, dass wir das gleiche Bild laden zuerst zweimal durch das Image-Objekt, und auch von Ajax im synchronen Modus. Das Objekt Image wird nicht benötigt, ich habe einfach angenommen, dass Sie es so laden möchten. Der Schlüssel ist jedoch, dass, wenn Ajax abgeschlossen ist, das Bild vollständig im Cache des Browsers heruntergeladen wird. Somit steht das Bild auch zur Verwendung durch das Objekt Image zur Verfügung.

Dies setzt voraus, dass das Image mit Cache-freundlichen HTTP-Header geliefert wird. Andernfalls kann das Verhalten in verschiedenen Browsern variieren.

Verwandte Themen