外部 API 最常見的用途之一,便是允許 ActionScript 應用程式與網頁瀏覽器進行通訊。利用外部 API,ActionScript 方法可以呼叫以 JavaScript 撰寫的程式碼,反之亦然。由於瀏覽器的複雜性以及在內部呈現頁面的不同方式,因此在執行 HTML 網頁的第一個 JavaScript 之前,並無法保證 SWF 文件可以註冊它的回呼。所以,透過 JavaScript 呼叫 SWF 文件中的函數之前,您的 SWF 文件永遠都要先呼叫 HTML 網頁,通知它 SWF 文件已經準備開始接收連線。
例如,透過由 IMManager 類別執行的一系列步驟,Introvert IM 就可以判斷瀏覽器是否已經準備開始進行通訊並準備通訊用的 SWF 檔。第一個步驟是判斷瀏覽器準備開始進行通訊的時間,此步驟會在 IMManager 建構函式中執行,如下所示:
public function IMManager(initialStatus:IMStatus)
{
_status = initialStatus;
// Check if the container is able to use the external API.
if (ExternalInterface.available)
{
try
{
// This calls the isContainerReady() method, which in turn calls
// the container to see if Flash Player has loaded and the container
// is ready to receive calls from the SWF.
var containerReady:Boolean = isContainerReady();
if (containerReady)
{
// If the container is ready, register the SWF's functions.
setupCallbacks();
}
else
{
// If the container is not ready, set up a Timer to call the
// container at 100ms intervals. Once the container responds that
// it's ready, the timer will be stopped.
var readyTimer:Timer = new Timer(100);
readyTimer.addEventListener(TimerEvent.TIMER, timerHandler);
readyTimer.start();
}
}
...
}
else
{
trace("External interface is not available for this container.");
}
}
首先,程式碼會使用
ExternalInterface.available
屬性,檢查目前的容器是否可以使用外部 API。如果可以使用,它就開始進行設定通訊的程序。由於當嘗試與外部應用程式進行通訊時,有可能會發生安全性例外和其它錯誤,因此程式碼會位於
try
區塊 (為保持程式碼簡潔,清單中會省略對應的
catch
區塊) 中。
程式碼接著會呼叫
isContainerReady()
方法,如下所示:
private function isContainerReady():Boolean
{
var result:Boolean = ExternalInterface.call("isReady");
return result;
}
然後
isContainerReady()
會使用
ExternalInterface.call()
方法呼叫 JavaScript 函數
isReady()
,如下所示:
<script language="JavaScript">
<!--
// ------- Private vars -------
var jsReady = false;
...
// ------- functions called by ActionScript -------
// called to check if the page has initialized and JavaScript is available
function isReady()
{
return jsReady;
}
...
// called by the onload event of the <body> tag
function pageInit()
{
// Record that JavaScript is ready to go.
jsReady = true;
}
...
//-->
</script>
isReady()
函數只會傳回
jsReady
變數的值。此變數的起始值是
false
,當觸發網頁的
onload
事件後,此變數的值才會變成
true
。換句話說,如果 ActionScript 在載入網頁前就呼叫
isReady()
函數,JavaScript 會將
false
傳回給
ExternalInterface.call("isReady")
,而使 ActionScript 的
isContainerReady()
方法傳回
false
。網頁一經載入後,JavaScript
isReady()
函數就會傳回
true
,因此 ActionScript
isContainerReady()
方法也會傳回
true
。
回到 IMManager 建構函式中,根據容器的準備狀態會發生下列兩種狀況的其中一種狀況。如果
isContainerReady()
傳回
true
,則程式碼只會呼叫
setupCallbacks()
方法,使用 JavaScript 來完成設定通訊的程序;另一種情況是,如果
isContainerReady()
傳回
false
,則會將程序暫停,並建立 Timer 物件,使其每 100 毫秒就呼叫一次
timerHandler()
方法,如下所示:
private function timerHandler(event:TimerEvent):void
{
// Check if the container is now ready.
var isReady:Boolean = isContainerReady();
if (isReady)
{
// If the container has become ready, we don't need to check anymore,
// so stop the timer.
Timer(event.target).stop();
// Set up the ActionScript methods that will be available to be
// called by the container.
setupCallbacks();
}
}
每當呼叫
timerHandler()
方法時,它會再檢查一次
isContainerReady()
方法的結果。一旦容器經過初始化,這個方法就會傳回
true
。然後程式碼就會停止執行 Timer 並呼叫
setupCallbacks()
方法,完成瀏覽器的通訊設定程序。