Flash(实际上是 Flex)对象是使用 embedCallAC_FL_RunContent.js 脚本的修改版本在更新面板内的 ASP.Net 页面上创建的,因此可以动态写入。使用此脚本重新创建它,并将每个部分回发到该面板。页面上还有其他更新面板。
对于一些回发(部分和全部),外部接口调用,例如在$get('FlashObj').ExternalInterfaceFunc('arg1', 0, true);
服务器端准备并使用 ScriptManager.RegisterStartupScript 添加到页面。它们嵌入在函数中并填充到 Sys.Application 的加载事件中,例如Sys.Application.add_load(funcContainingExternalInterfaceCalls)
.
问题在于,因为 Flash 对象的状态状态可能会随着每次部分回发而改变,所以当 JavaScript -> Flash 外部接口调用被调用时,Flash (Flex) 对象和/或外部接口可能还没有准备好,甚至还存在于 DOM 中. 它会导致“对象不支持此属性或方法”异常。
如果 Flash 准备好,我有一个工作策略立即进行 ExternalInterface 调用,否则将它们排队,直到 Flash 宣布准备好。
//Called when the Flash object is initialized and can accept ExternalInterfaceCalls
var flashReady = false;
//Called by Flash when object is fully initialized
function setFlashReady() {
flashReady = true;
//Make any queued ExternalInterface calls, then dequeue
while (extIntQueue.length > 0)
(extIntQueue.shift())();
}
var extIntQueue = [];
function callExternalInterface(flashObjName, funcName, args) {
//reference to the wrapped ExternalInterface Call
var wrapped = extWrap(flashObjName, funcName, args);
//only procede with ExternalInterface call if the global flashReady variable has been set
if (flashReady) {
wrapped();
}
else {
//queue the function so when flashReady() is called next, the function is called and the aruments are passed.
extIntQueue.push(wrapped);
}
}
//bundle ExtInt call and hold variables in a closure
function extWrap(flashObjName, funcName, args) {
//put vars in closure
return function() {
var funcCall = '$get("' + flashObjName + '").' + funcName;
eval(funcCall).apply(this, args);
}
}
每当我更新包含 Flash (Flex) 对象的更新面板时,我都会将 flashReady var 设置为脏。
ScriptManager.RegisterClientScriptBlock(parentContainer, parentContainer.GetType(), "flashReady", "flashReady = false;", true);
我很高兴我让它工作,但感觉就像一个黑客。对于诸如闭包之类的概念,我仍在学习曲线上,为什么“eval()”显然是邪恶的,所以我想知道我是否违反了一些最佳实践,或者是否应该改进此代码,如果是的话如何?谢谢。