[sc name="zhuanzai" author="Barranca" link="
https://www.davidebarranca.com/2014/12/html-panels-tips-15-asynchronous-vs-synchronous-evalscript/
" ][/sc]
引用
StackOverflow
:
当您同步执行某事时,您会等待它完成,然后再继续执行另一个任务。当您异步执行某件事时,您可以在它完成之前继续执行另一个任务。
或者视觉上:
早期
evalScript
是同步的,现在则是异步的:
CSXSInterface.instance.evalScript('jsxFunction'); // Sync 同步
csInterface().evalScript('jsxFunction'); // Async 异步
evalScript 函数需要两个参数:
要运行的 ExtendScript 代码。
一个回调函数,它反过来将来自 ExtendScript 调用的返回值作为参数。
默认行为如下:
var csInterface = new CSInterface();
var username = undefined;
// AE 脚本中 获取当前系统用户名
csInterface.evalScript('system.userName', function(result) {
username = result;
alert(username); // undefined
在上面的例子中,system.userName执行后会直接返回——当前在 AE中的数据被传递给回调,回调将其分配给变量username。由于evalScript的异步性质,最后一句显示“未定义” :第 6 行还未执行完毕,解释器就会继续执行到第 9 行而不等待 ExtendScript 返回(4~7行),因此username 仍然是undefined。
就如同:你让你老婆出去买东西,然后她前脚刚出门,你就打开冰箱说“老婆!你买的东西呢!”
同步解决方法
有几种不同的方法可以模拟同步行为
1.设置超时
最简单的方法:等你老婆从商店回来:
var csInterface = new CSInterface();
var username = undefined;
csInterface.evalScript('system.userName', function (result) {
username = result;
setTimeout(alert(username), 500); // 延迟500ms再弹窗
这并不理想。因为不知道要等待多长时间 – 这取决于要执行的 ExtendScript 代码。
2. 在回调中嵌套代码
如果alert在回调中使用,则它可以正常工作:
var csInterface = new CSInterface();
var username = undefined;
csInterface.evalScript('system.userName', function (result) {
username = result;
alert(username);
当然,这会导致所谓的回调地狱 ——将 evalScript 调用嵌套在另一个调用中,例如:
csInterface.evalScript('/* 你的代码1 */', function(result) {
csInterface.evalScript('/* 你的代码2 */', function (result) {
// 等等
如果你没有特别的需求,它也能凑合用。
3. 事件驱动回调
从 CEP 5.2 开始支持此方法。可以通过PlugPlugExternalObject实现自定义事件,这些事件由 ExtendScript 调度并从 JS 侦听。
先把 ExtendScript 代码放在 JSX 文件中:
// in jsx file
function get_username() {
// 调用lib
try {
var xLib = new ExternalObject("lib:PlugPlugExternalObject"); // 老版本用lib:// ?待验证
} catch (e) {
return false;
var eventObj = new CSXSEvent(); // 创建事件对象
eventObj.type = "my_event"; // 创建事件类型,用于外部验证
eventObj.data = system.userName;// 输入事件数据
eventObj.dispatch(); // 发送事件
xLib.unload(); // 注销lib?
return true;
然后在 JS 中设置监听器,用于监听数据的接受;
var csInterface = new CSInterface();
// 监听
csInterface.addEventListener("my_event", function (event) {
alert(event.data); // 返回接受的数据
// 判断是否正常执行lib
csInterface.evalScript("get_username()", function (result) {
if (result == false) {
alert("There's been a problem.");
请注意,正如Kris Coppieters等其他开发人员所假设的那样,“即使您设法从 JS 的不同部分进行多个 JSX 调用,也可能无法同时运行多个 ExtendScript ”。
(1)如果3的事件是绑定在单击事件上的,你需要先侦听获取事件,再处理完事件后,注销。否则每次单击都会只addListen,多次执行
function test() {
var csInterface = new CSInterface();
function get_data(event) {
alert(event.data);
csInterface.removeEventListener("my_event", get_data);
csInterface.addEventListener("my_event", get_data);
csInterface.evalScript("get_username()", function (result) {
if (result == false) {
alert("未成功加载lib");
(2)JSX传回js的类型为字符串,所以想传对象回来,需要先在JSX里return JSON.stringify(你的对象),然后在js里 JSON.parse(返回值)