2007年02月11日

Load and Execute JavaScript on Demand

ajax javascript xmlhttprequest

這是一個使用在本部落格的技巧,用於因應樂多部落格系統之限制。

傳統上,我們執行 JavaScript 程式的方式是靜態的,在 HTML 文件中以 <script type="text/javascript" src="example.js"></script> 的敘述載入並執行外部 JavaScript 程式。若我們無法使用上述方式時,就需要動態載入與執行。另一種需要動態載入與執行 JavaScript 程式的時機為,存在幾個相當龐大的 JavaScript 程式但不全部都用得到的情形,為了降低瀏覽器載入的時間,此時我們需要依某些條件決定那些 JavaScript 程式需要載入。


欲於 JavaScript 程式中動態載入其他 JavaScript 程式必須利用 XmlHttpRequest 才可自伺服器取得其他 JavaScript 程式的內容,接著再調用 window.eval(responseText) 執行載入的程式內容。基本上不是很困難的動作,但實際使用時卻有一個很大的效能缺陷。如果外部 JavaScript 程式存在執行順序的相依性,則我們通常須以 XmlHttpRequest 的「同步」模式取得外部 JavaScript 程式內容,但這卻將帶來非常明顯的瀏覽器停滯現象。在同步模式下,瀏覽器為了等待文件完成載入動作會擱置其他檔案的載入動作。當外部 JavaScript 程式不只一個時,使用者將明顯地感受到瀏覽器的停滯現象。

在實踐過程中,我發現大多數瀏覽器以 <script type="text/javascript" src="example.js"></script> 的敘述靜態載入 JavaScript 程式時,採非同步載入但依序執行的策略。所以載入外部程式的動作不會產生明顯的停滯現象。因此實踐動態載入 JavaScript 程式之需求時,我們需「非同步」載入外部程式,但「同步」依序執行,以避免瀏覽器的停滯現象。

我的實踐概念是以 XmlHttpRequest 的非同步模式取得所有外部 JavaScript 程式的內容。欲載入的 JavaScript 程式之位址置於 scripts 陣列中,載入後的程式內容存於 loadedScripts 陣列。再以 Interval 設定時間間隔探詢是否已完成所有外部 JavaScript 程式的載入動作 (loadingScripts == 0。容我提醒,因為我們以非同步模式於載入主文件時並行載入外部 JavaScript 程式。在非同步模式下,我們不能肯定是主文件先下載完成亦或外部檔案先下載完成,故不能用 window.onload

當所有外部程式皆已載入後,再依 scripts 的順序,執行載入的程式。執行程式必須使用 window.eval() 才能將執行時產生的個體置於 window scope 中 (簡單說即令那些個體成為全域變數) 。

下列是實作範例。示範動態載入 Yahoo UI Library 的內容之後,再以 Yahoo UI Library 的 API 設定 "Hello world" 的位置。這也可以示範為何我們必須用 window.eval() ,如果將 window.eval() 改為 eval() ,則稍候的 YAHOO.util.Dom.getXY() 動作會發生錯誤,錯誤訊息為 YAHOO 個體未定義。此因單純用 eval() 執行時所定義的 YAHOO 個體不是處於 window scope 中,而是在一個 local scope ,故 JavaScript 會找不到 YAHOO 個體。


Posted by shirock at 樂多Roodo! │23:18 │回應(0)引用(1)JavaScript
樂多分類:網路/3C 共同主題:JavaScript範例 工具:編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/2716520
引用列表:
利用 document.createElement(\'script\') 實踐動態載入外部 javascript 的技巧
Load and Execute JavaScript on Demand, by createElement【石頭閒語】 at 2007年02月17日 14:45