Очередь ExternalInterface вызывает Flash-объект в UpdatePanel - Нужно улучшение? - PullRequest
0 голосов
/ 09 июня 2010

Объект Flash (фактически Flex) создается на странице ASP.Net в панели обновлений с использованием модифицированной версии сценария embedCallAC_FL_RunContent.js, поэтому его можно записывать динамически. Он воссоздается с помощью этого сценария при каждой частичной обратной передаче на эту панель. На странице также есть другие панели обновления.

При некоторых обратных передачах (частичных и полных) вызовы внешнего интерфейса, такие как $get('FlashObj').ExternalInterfaceFunc('arg1', 0, true);, подготавливаются на стороне сервера и добавляются на страницу с помощью ScriptManager.RegisterStartupScript. Они встроены в функцию и вставлены в событие загрузки Sys.Application, например, Sys.Application.add_load(funcContainingExternalInterfaceCalls).

Проблема заключается в том, что, поскольку состояние состояния объекта Flash может изменяться при каждой частичной обратной передаче, объект Flash (Flex) и / или внешний интерфейс могут быть не готовы или даже не существовать в DOM, когда JavaScript -> внешний интерфейс Flash звонок сделан. Это приводит к исключению « Object не поддерживает это свойство или метод ».

У меня есть рабочая стратегия, позволяющая немедленно выполнять вызовы ExternalInterface, если Flash готов, или помещать их в очередь до тех пор, пока 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);
        }
    }

Я устанавливаю для flashReady var значение «dirty» при каждом обновлении панели обновления, содержащей объект Flash (Flex).

ScriptManager.RegisterClientScriptBlock(parentContainer, parentContainer.GetType(), "flashReady", "flashReady = false;", true);

Я рад, что заставил его работать, но это похоже на взлом. Я все еще нахожусь на кривой обучения в отношении таких понятий, как замыкания, почему «eval ()», по-видимому, является злом, поэтому мне интересно, нарушаю ли я некоторые передовые методы или этот код должен быть улучшен, если да, то как? Спасибо.

1 Ответ

0 голосов
/ 10 июня 2010

К сожалению, мне пришлось делать обходные пути, очень похожие на то, что вы делаете, и с проверкой, чтобы убедиться, что Flash готов принимать вызовы, и затем с очередями.

Это известная проблема, которая вызываетнесколько быстрых последовательных вызовов ExternalInterface (ближе к 400 мсек) могут привести к тому, что некоторые из них будут проигнорированы или отброшены.

Я чувствую вашу боль!

...