2010-02-17 67 views
5

我需要做這樣的事情:的Javascript塊腳本執行

  • 執行一段代碼
  • 開始加載圖像,並阻止腳本執行
  • 當圖像被加載恢復執行
  • 執行代碼的其餘部分

我知道最簡單的方法是在圖像的onload事件指定功能然後執行函數中的其餘代碼,但是如果可能的話,我想要一個阻止腳本執行的「線性」行爲,然後恢復它。 那麼,是否有跨瀏覽器的方式來做到這一點?

回答

3

阻止腳本執行的唯一方法是使用一個循環,這也將鎖定大多數瀏覽器和防止與你的網頁的任何交互。

Firefox,Chrome,Safari,Opera和IE 全部支持complete屬性,最終在HTML5中進行了標準化。這意味着您可以使用while循環停止腳本執行,直到圖像完成下載。

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

// script continues after image load 

話雖這麼說,我覺得你應該看看沒有鎖定了瀏覽器實現目標的途徑。

+0

我同意這是一種糟糕的方式,但我認爲這是唯一的方法。也許我可以給用戶在阻止腳本執行和加載圖像時調用加載函數的可能性。 – mck89

+0

@ mck89:我很難相信這是唯一的方法。我可以誠實地說,我從來沒有遇到JavaScript需要鎖定腳本的情況;總是有一種方法(比如臨時覆蓋函數)異步執行任務。畢竟,您在頁面上控制腳本。也許你可以發佈另一個問題,更詳細地討論你的問題? –

+0

@ mck89:'完整'屬性存在Gecko和IE,並可能在其他瀏覽器中工作。如果您堅持阻止腳本執行,請參閱我的更新。 –

1

如果你不介意的預處理步驟,嘗試Narrative Javascript,您可以

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

這是一個偉大的項目,但我試圖在純JavaScript中構建一個簡單的應用程序......並且我不知道Java的任何內容:) – mck89

+0

@ mck89:預處理後,您將獲得純Javascript。 – kennytm

+0

是的,我知道,但我更喜歡只使用JavaScript – mck89

1

這個建議不完全是你要求的,但我提供它作爲一個可能的選擇。

用你想要使用的background-image創建一個CSS類。當你的應用程序啓動時,將這個CSS類分配給一個DIV,該DIV可以隱藏在站點之外或大小爲零零像素。這將確保圖像從服務器加載。當你想加載圖像(上面的第二步)時,使用你創建的CSS類;這會很快發生。也許足夠快,你不需要阻止後續的代碼執行?

+0

是的,這可能是一個很好的圖像預加載方法,但我沒有在應用程序的開始加載圖像。 – mck89

+0

我明白了,但是如果您創建了具有背景圖像屬性的CSS類,則將該類分配給虛擬DIV,您將在應用程序開始時加載圖像。 – Upperstage

1

我不會嘗試完全阻止腳本執行,因爲這可能會導致瀏覽器變慢,甚至會提醒用戶腳本執行時間過長。

你可以通過使用事件來完成工作來「線性化」你的代碼。您將需要添加一個超時功能,因爲圖像可能永遠不會加載。

實施例:

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

你確定你可以用setTimeout來停止執行嗎? – mck89

+0

這不會停止代碼執行,它允許您等到圖像完成加載後再做更多工作。通過將剩餘的代碼移入finishWork函數,您可以「停止」自己的代碼執行。 – FlashXSFX

1

可以使用XMLHttpRequest和使用同步模式。

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); 

這裏的竅門是我們加載相同的圖像兩次,第一次使用Image對象,並且還通過在同步模式中使用AJAX。 Image對象不是必需的,我只是假設你想要加載它。關鍵是如果ajax完成,那麼圖像將被完全下載到瀏覽器的緩存中。因此,該圖像也可供Image對象使用。

這確實假定圖像是與緩存友好的http頭一起提供的。否則,它的行爲在不同的瀏覽器中可能會有所不同。