Quick tip: ExternalInterface.call is synchronous!

It is a little wonder to me how flash player communicates with JavaScript. Calls are fully synchronous, it works as those (fp and js) were fully integrated into each other. To simulate this lets test some simple flow:

Flash Player calls JavaScript
    JavaScript calls FlashPlayer
        FlashPlayer do some stuff and finishes
    JavaScript finishes
FlashPlayer continues

Following flex application runs simple JavaScript:

document.getElementById("flash").universalCallback();
return "synchronous return";
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    applicationComplete="init()">
<mx:Script>
<![CDATA[
    [Bindable]
    private var lastResult:String = "";

    private function init():void
    {
        ExternalInterface.addCallback("universalCallback", universalCallback);
    }

    private function runScript():void
    {
        var script:String = 'document.getElementById("flash").universalCallback();' + 
                'return "synchronous return";';
        
        var result:String = ExternalInterface.call("function(){" + script + "}");
        lastResult += result + "\n";
    }

    private function universalCallback(... rest):void
    {
        lastResult += "universalCallback" + "\n";
    }
]]>
</mx:Script>
<mx:Button click="runScript()" label="Run"/>
<mx:TextArea width="100%" height="100%" text="{lastResult}" />
</mx:Application>

and results are logged into TextArea:

universalCallback
synchronous return

This means that ExternalInterface.call() is synchronous and waits until called JavaScript finishes. Just after that, flash player moves on the next line. This interesting behaviour makes flash player to hold (but not to freeze) on one line while it is able to continue on different execution (universalCallback()).

Notice, JavaScript to ActionScript data can be sent via ExternalInterface.addCallback() or simple by synchronous return:

var result:String = ExternalInterface.call("function(){" + script + "}");

however, you can not use eval method this way!

var result:String = ExternalInterface.call("eval", script);

Leave a comment

Please be polite and on topic. Your e-mail will never be published.