2009-09-28 72 views
2

我有一個Javascript API,它應該可以與GWT和Flex一起使用。使用FABridge,從AS3調用Javascript方法非常簡單,反之亦然。但是,當我嘗試在我的Javascript API中註冊回調到AS3方法時,我卡住了。下面是一個簡短的代碼示例:從Javascript調用Flex/AS3回調

public function initApp():void { 
    if (ExternalInterface.available) { 
     ExternalInterface.addCallback("foobar", foobar); 
} 
} 

public function foobar():void { 
    //the callback function 
    Alert.show("Callback from API works!"); 
} 

private function btnCallbackClicked():void { 
    ExternalInterface.call("testAPICallbackFromJS", Application.application.foobar); 
} 

和簡單的JS方法:

function testAPICallbackFromGWT(callback){ 
    $clinit_26(); //added by the GWT compiler 
    alert('callback to be launched 3 2 1'); 
    callback(); 
} 

但是這個版本不工作,因爲我總是在我的JS代碼收到一個空的功能。看起來FABridge正在削減其餘部分。 然後我嘗試了一種不同的方法。我寫了一個小的JS方法,它接受函數的名稱並從JS端創建回調。

registerFlexCallback = function(registerMethod, callback, id) { 
    /* 
    workaround to create a callback for an AS method, which can be called by Javascript 
     * registerMethod - Javascript method which shall be called for registration with the created callback as parameter 
     * callback - AS method that shall be called by Javascript (available over the FABridge interface) 
     * id - ID of the flash object (use Application.application.id in AS) 
    */ 
    var swf = document.getElementById(id); 
    eval(registerMethod + "(swf." + callback + ");"); 
}; 

這一個適用於Internet Explorer,但沒有其他瀏覽器。例如,在Firefox中,我得到了以下錯誤消息:

NPMethod called on non-NPObject wrapped JSObject! 

有人可以告訴我,這是什麼錯誤是關於(也許某種安全問題的)?或者有沒有人有一個更好的主意,如何創建可以由JS調用我的AS3方法的回調?

回答

2

這是因爲函數不能通過FABridge序列化。在你的意思

ExternalInterface.call("testAPICallbackFromJS", Application.application.foobar); 

第二個參數將始終爲空。我所做的是通過eval在HTML頁面上添加一個包裝器方法,該方法指向我的嵌入並因此添加回調。所以,你必須添加一個額外的,而惱人的步驟:

ExternalInterface.addCallback("foobar", foobar); 

var callBack:String = ""; 
var functionName:String = UIDUtil.createUUID; 
callBack = "function " + functionName + "(){ " + 
"document.getElementById('applicationName').foobar(arguments);"+ 
"}"; 
ExternalInterface.call("eval", callback); 


ExternalInterface.call("testAPICallbackFromJS", functionName); 

你看到我敢肯定的NPObject錯誤是安全錯誤(基於它來自哪裏的FF代碼)可能阻止你從動態注入的方法,可以被評價而沒有JS解釋器阻礙。

我甚至沒有試圖編譯上述所以希望你能得到要點。

+0

非常感謝您的幫助,它現在正常運作!只有兩件事,如果您使用UIDUtil.createUID()創建JS函數名稱,則應在開頭添加一個字母並替換全部「 - 」,否則它似乎不是正確的JS函數名稱,也不會工作。另外我還需要在我的JS代碼中調用函數名,因爲它只是一個字符串而沒有函數指針。有一個更好的方法嗎? – SilentGert 2009-09-29 00:17:11

+0

好的一點,關於JS中的方法名稱。實際上,我並沒有使用UUID,但是,這是我所能想到的!你可以直接在JS中通過名稱調用它們的函數,如下所示: this [functionName] .apply(arrayOfParameters); 但使用eval沒有多大區別。 – dan 2009-09-29 14:21:31

1

我注意到兩件事情馬上

首先出現,如果ExternalInterface的是沒有準備好你的ExternalInterface的會死。

public function initApp():void { 
    if (ExternalInterface.available) { 
    ExternalInterface.addCallback("foobar", foobar); 
} 
} 

我會添加一個timout,然後再試一次,以便它再次嘗試,直到Externalinterface準備就緒。

另外我沒有在你的javascript代碼中看到函數「foobar」。我看到回調作爲一個變量傳入,但沒有將它改爲實際上是'foobar',這是一種可以使測試成爲錯誤事件的事情。

function testAPICallbackFromGWT(callback){ 
    $clinit_26(); //added by the GWT compiler 
    alert('callback to be launched 3 2 1'); 
    callback(); 
} 

我會簡化您的測試示例,以減少運動部件。

// e.g. run just flash to javascript only 
ExternalInterface.call("alert", "hello out there"); 

是否可行

// establish the call from flash 
ExternalInterface.addCallback("hello_out_there", foobar); 

// and in javascript 
alert(typeof('hello_out_there')); // will be 'function' if exists or undefined if ExternalInterface did not work 

這樣你就可以得到一個處理逐位進行什麼工作,在那裏它打破了。

注意時機,如果你可以從按鈕動作和你的JavaScript從鏈接中閃出你也可以消除一些加載問題。當然,您需要爲您的啓動解決自動加載版本,但是對於手動觸發的事件進行測試可以顯着簡化事情。

也因爲它的JavaScript瀏覽器是相關的。

我在Firefox和Internet Explorer中看到了一致的結果,它在Safari瀏覽器中發生故障,有時IE瀏覽器出現了奇怪的瀏覽器。

有時Firefox是唯一一個打破。

你只需要測試它們。

+0

感謝提示與超時,但我沒有問題從AS調用JS方法或從JS調用AS方法(硬編碼函數名稱)。這工作得很好。我的問題是我無法爲我的AS方法創建回調,並在我的JS方法中使用它們。 – SilentGert 2009-09-29 00:21:24