【发布时间】:2012-05-28 21:49:37
【问题描述】:
Javascript 的setTimeout 函数是window 对象的一个方法。此对象在 ExtendScript 中不存在,因此不可用于为 Adobe InDesign 或 Illustrator 制作的脚本。我可以改用什么来获得相同的结果?
【问题讨论】:
标签: adobe settimeout extendscript adobe-indesign
Javascript 的setTimeout 函数是window 对象的一个方法。此对象在 ExtendScript 中不存在,因此不可用于为 Adobe InDesign 或 Illustrator 制作的脚本。我可以改用什么来获得相同的结果?
【问题讨论】:
标签: adobe settimeout extendscript adobe-indesign
它是扩展脚本的$ 对象的一部分。
$.sleep(1000) //tell extendscript to sleep 1000 milliseconds
与 setTimeout() 不同,但你应该能够让它为你工作。
编辑:这是扩展脚本的 setTimeout 扩展:
$.setTimeout = function(func, time) {
$.sleep(time);
func();
};
$.setTimeout(function () {alert("hello world")}, 3000);
【讨论】:
var t = setTimeout(stopPooling, 10000) 这样的东西。如果通过池化日志我可以确定外部应用程序成功终止(不到10秒),那么我需要取消超时(clearTimeout(t)),以免不必要地调用stopPooling。
func();修改为if(!appRan) func();吗?我不知道如何在扩展脚本中编写 clearTimeout()。
var t, i; i=setInterval(function() { if(appRan) { clearInterval(i); clearTimeout(t); handleAppSuccess(); }}, 100); t=setTimeout(function() { clearInterval(i); handleAppFailed(); }, 10000); 这样的东西我想我可以用$.sleep 使用计数器来做到这一点:for(c=0; c<100; ++c){ $.sleep(100); if(appRan){ success=true; c=101; }} if(success){ handleAppSuccess(); } else { handleAppFailed(); },但其他情况可能需要真正的非阻塞方法......
app.executeCommand 这样的异步操作完成很有用
有一个 setTimeout ExtendScript 实现 here(德国网站,代码用英文注释),但由于它依赖于 app.idleTasks,它只能在 InDesign 中工作(没有 Photoshop)。
我将上面链接中的可下载代码粘贴到此处 (© Andreas Imhof):
/**
* setTimeout
* Version 1.0
* A setTimeout function implementation for InDesign ExtendScript like known from a Browser's Javascript.
* Uses InDesign's idleTask stuff.
* Timeout milliseconds are not accurate, but it allows to call a heavy load script,
* split it up into small junks for InDesign is not blocked too long and has time to breath.
*
* The script MUST run in its dedicated target engine:
* #target "InDesign"
* #targetengine "myOwnEngineName"
*
* DISCLAIMER:
* No warranty - use as is or modify but retain the originator's coordinates:
* CopyRight Andreas Imhof, www.aiedv.ch, ai@aiedv.ch
*/
//
var setTimeout_Task_curfile = new File($.fileName),
setTimeout_Task_curfullname = decodeURI(setTimeout_Task_curfile.name),
// setTimeout_Taskname must be a UNIQUE name, so we take it from the current running script!!
// May be set to any String like
// setTimeout_Taskname = 'myOwnTask';
setTimeout_Taskname = setTimeout_Task_curfullname.lastIndexOf(".") > 0 ? (setTimeout_Task_curfullname.substr(0,setTimeout_Task_curfullname.lastIndexOf("."))) : setTimeout_Task_curfullname,
setTimeout_Tasks = {}, // all defined tasks prepared to run
/**
* setTimeout_hasIdleTask
* Utility function
* @param {Number} the timeout task id
* @return {Boolean} true if a given timeout id also has his attached idleTask
*/
setTimeout_hasIdleTask = function(id) {
var has = false, i;
for (i = 0; i < app.idleTasks.length; i++) {
//alert("id: " + id + " tid: " + app.idleTasks[i].label);
if (app.idleTasks[i].isValid && (app.idleTasks[i].id === id)) {
has = true;
break;
}
}
return has;
},
/**
* setTimeoutList
* Utility function
* @return {String} a list of all currently active setTimeout_Tasks
*/
setTimeoutList = function() {
var list = "", cb,
k;
for (k in setTimeout_Tasks) {
if (list !== "") list += ",";
cb = setTimeout_Tasks[k]["cb"].toString();
cb = cb.replace(/\s/g,"");
list += setTimeout_Tasks[k]["taskid"] + ":" + cb;
}
return list;
},
/**
* idleTasksList
* Utility function
* @return {String} a list of all currently active idleTasks
*/
idleTasksList = function() {
var list = "",
k;
for (k = 0; k < app.idleTasks.length; k++) {
if (list !== "") list += ",";
list += app.idleTasks[k].id + ":" + setTimeout_hasIdleTask(app.idleTasks[k].id) + ":" + app.idleTasks[k].label;
}
return list;
},
/**
* setTimeoutInit
* Init/clean the timeout system
*/
setTimeoutInit = function() {
var it;
// remove all (erroneous) idleTasks
//alert("set idleTasks: " + app.idleTasks.length);
//NA: logmess("setTimeoutInit set idleTasks: " + app.idleTasks.length + "\n");
for (it = 0; it < app.idleTasks.length; it++) {
if (app.idleTasks[it].label == setTimeout_Taskname) {
//alert("removing idleTask id " + app.idleTasks[it].id + " label: " + app.idleTasks[it].label);
clearTimeout(app.idleTasks[it].id);
}
}
setTimeout_Tasks = {};
},
/**
* Tasks Handler
* Check if a task can be called now
* @param {Number} taskid
* @return {Boolean} always false
*/
setTimeoutHandler = function(taskid) {
var now_Ticks = new Date().getTime(),
cb, cb_retval = undefined;
try {
//alert("taskid: " + taskid + "\nnumcalls: " + setTimeout_Tasks[taskid]["numcalls"]);
// we look for well timed call only!!! CS6 calls at start AND after the timeout
if (setTimeout_Tasks[taskid]["end_ticks"] > now_Ticks) { // we have not reached timeout
//NA: logmess("setTimeoutHandler id " + taskid + " too early by ms: " + (setTimeout_Tasks[taskid]["end_ticks"] - now_Ticks) + "\n");
//alert("setTimeoutHandler id " + taskid + " too early by ms: " + (setTimeout_Tasks[taskid]["end_ticks"] - now_Ticks));
setTimeout_Tasks[taskid]["numcalls"] += 1;
return false; // wait for next call
}
}
catch(ex) {
alert("Exception (1) in function 'setTimeoutHandler()', taskid " + taskid + ":\n" + ex);
}
try {
cb = setTimeout_Tasks[taskid]["cb"]; // store the callback
clearTimeout(taskid); // remove the timeout
}
catch(ex) {
alert("Exception (2) in function 'setTimeoutHandler()', taskid " + taskid + ":\n" + ex);
}
try {
//NA: logmess("setTimeoutHandler call " + cb + "\n");
cb_retval = cb(); // call the cb
//if (cb_retval) alert("cb_retval:\n" + cb_retval);
} catch(ex) {
alert("Exception in function '" + cb() + ":\n" + ex);
}
return false;
},
/**
* setTimeout
* Set a function to called after the given timeout
* @param {function} callback the function to call
* @param {Number} timeout in ms
* @return {Boolean} null on error, otherwise the id (can be used with clearTimeout
*/
setTimeout = function(callback,timeout) {
try {
var idle_Task,
now_Ticks = new Date().getTime();
idle_Task = app.idleTasks.add({sleep:timeout});
idle_Task.label = setTimeout_Taskname;
setTimeout_Tasks[idle_Task.id] = {
"label": setTimeout_Taskname,
"start_ticks": now_Ticks,
"sleep": timeout,
"end_ticks": now_Ticks + timeout,
"cb": callback,
"taskid": idle_Task.id,
"numcalls": 0
};
setTimeout_Tasks[idle_Task.id].handler = function(ev){setTimeoutHandler(setTimeout_Tasks[idle_Task.id]["taskid"]);};
idle_Task.addEventListener(IdleEvent.ON_IDLE, setTimeout_Tasks[idle_Task.id].handler,false);
//NA: logmess("setTimeout idle_Task.id: " + idle_Task.id + ", timeout: " + timeout + "\ncallback: " + callback + "\n");
return idle_Task.id;
}
catch(ex) {
alert("Exception in function 'setTimeout()':\n" + ex);
}
return null;
},
/**
* clearTimeout
* Clear the timeout given by the setTimeout return value
* @param {Number} id the timeout id to clear
*/
clearTimeout = function (id){
var i, task = null;
for (i = 0; i < app.idleTasks.length; i++) {
//alert("id: " + id + " tid: " + app.idleTasks[i].label);
if ((app.idleTasks[i].id == id) && app.idleTasks[i].isValid) {
task = app.idleTasks[i];
break;
}
}
if (task !== null) {
try {
if (setTimeout_Tasks[id] && setTimeout_Tasks[id].handler) {
// this kills any!!! app.idleTasks.itemByID(id).removeEventListener(IdleEvent.ON_IDLE, setTimeout_Tasks[id].handler,false);
task.removeEventListener(IdleEvent.ON_IDLE, setTimeout_Tasks[id].handler,false);
}
// this kills any!!! app.idleTasks.itemByID(id).remove();
//task.remove();
task.sleep = 0;
}
catch(ex) {
alert("Exception in function 'clearTimeout() idleTasks':\n" + ex);
}
try {
delete setTimeout_Tasks[id];
}
catch(ex) {
alert("Exception in function 'clearTimeout() delete setTimeout_Tasks':\n" + ex);
}
}
};
/**
* Init/clean the timeout system
*/
setTimeoutInit();
// alert(setTimeout_Taskname); // Just to check if the 'setTimeout_Taskname' was set correctly
【讨论】:
在 Adobe After Effects 中使用 $.sleep(time) 会导致脚本停止。
改为在 ExtendScript 中使用原生 app.scheduleTask(stringToExecute, delay, repeat):
例子:
var taskId = app.scheduleTask(function () {alert("hello world")}, 1500, false);
取消:
app.cancelTask(taskId);
【讨论】:
Error: ReferenceError: app is not defined?
app 是外部 .jsx 脚本文件的 Extendscript 的一部分(例如,当您在图层属性上使用表达式时除外)。请参阅ae-scripting.docsforadobe.dev/general/application/… - 我认为我实际上犯了一个错误,app.setTimeout() 本身不支持,我认为 After Effects 中的标准教程面板之一添加了该例程。
app.scheduleTask is not a function。知道如何解决这个问题吗?