Javascript's setTimeout
function is a method of the window
object. This object doesn't exist in ExtendScript and is therefore not available to scripts made for Adobe InDesign or Illustrator. What can I use instead to acheive the same results?
Is there an equivalent of setTimeout in Adobe's ExtendScript
Asked Answered
It's part of the extendscript's $
object.
$.sleep(1000) //tell extendscript to sleep 1000 milliseconds
Not the same as setTimeout() but you should be able to make it work for you.
EDIT: Here is setTimeout extension for extendscript:
$.setTimeout = function(func, time) {
$.sleep(time);
func();
};
$.setTimeout(function () {alert("hello world")}, 3000);
If you can test the success of running the external application couldn't you modify
func();
to if(!appRan) func();
? I don't know how to approach writing clearTimeout() in extendscript. –
Rains I suppose so.. But I have two different things to time. I want to pool my log file every 0.1 seconds, and also timeout after 10 seconds. Something like
var t, i; i=setInterval(function() { if(appRan) { clearInterval(i); clearTimeout(t); handleAppSuccess(); }}, 100); t=setTimeout(function() { clearInterval(i); handleAppFailed(); }, 10000);
I guess I could do this with $.sleep
using a counter: for(c=0; c<100; ++c){ $.sleep(100); if(appRan){ success=true; c=101; }} if(success){ handleAppSuccess(); } else { handleAppFailed(); }
, but other situations may require a real non-blocking method... –
Boarer this does also not unwind the stack / push the task at the end of the event loop. –
Earthen
this is useful to wait for async actions like
app.executeCommand
to finish –
Maltz THIS IS WORKING THANK YOU. –
Adept
This is very different from setTimeout: with setTimeout, the execution goes on in parallel. With sleep, the execution is halted. There are very few proper uses for sleep. Also note that, in InDesign, the display won’t refresh during sleep. –
Boothman
There is a setTimeout ExtendScript implementation here (German site, with code commented in english), but since it relies on app.idleTasks
, it works in InDesign only (no Photoshop).
I paste here the downloadable code found in the link above (© 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, [email protected]
*/
//
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
In Adobe After Effects using the $.sleep(time)
will cause the script to stall.
Instead use the native app.scheduleTask(stringToExecute, delay, repeat)
in ExtendScript:
Example:
var taskId = app.scheduleTask(function () {alert("hello world")}, 1500, false);
To cancel:
app.cancelTask(taskId);
how can I avoid
Error: ReferenceError: app is not defined
? –
Motte @Motte
app
is part of the Extendscript for external .jsx Script files (e.g. not when you use Expressions on Layer Properties). See ae-scripting.docsforadobe.dev/general/application/… - I think I made a mistake actually, app.setTimeout() is not natively supported, I think one of the standard tutorial panels in After Effects added the routine. –
Mckissick In Photoshop
app.scheduleTask is not a function
. Any idea how to get around this? –
Mandel © 2022 - 2024 — McMap. All rights reserved.
var t = setTimeout(stopPooling, 10000)
. If by pooling the log I can determine that the external application terminated successfully (under 10 seconds), then I need to cancel the timeout (clearTimeout(t)
) so as not to callstopPooling
unnecessarily. – Boarer