Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Anything similar to javascript's setInterval in ExtendScript?

Guest
Mar 10, 2014 Mar 10, 2014

I need a way to poll my server for new jobs for the illustrator script to work on every few hours.

I tried with $.sleep(), but that is blocking, I need a non-blocking way to do this.

Any advice?

Thanks!

Kashmira

TOPICS
Scripting
8.5K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Mentor ,
Mar 10, 2014 Mar 10, 2014

I have often wondered the same thing and researched it pretty extensively but to no avail. I am still wondering if there is some hack approach using dates, loops or practically anything to make a home brewed interval timer. But it seems like no. Even using Date for checking pretty much ends up emulating $sleep() from my tests. Why Adobe omitted common timers and intervals from the internal JS is beyond me, setInterval and setTimeout would be so useful, likewise the lack of mouse events, both those would open up entire new worlds of possibilities.

Here is a thread in the InDesign forum speaking of "app.scheduleTask" using Bridge: app.scheduleTask(script, delay [, repeat])

http://forums.adobe.com/message/3706907#3706907

I tried the "app.scheduleTask" approach and never got it working in Illustrator however. <-- I hope someone proves otherwise and says it is possible in Illustrator, please let me know if you do. Otherwise I don't think there are any solutions via JS. Maybe a timer in Applescript or VBScript however running in the background and working with Illustrator externally would be an alternative.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 12, 2014 Mar 12, 2014

Thank you! I will try using scheduleTask and update this thread on my findings.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 12, 2014 Mar 12, 2014

Ok, so here is what *might* work for what I need to do:

This wakes up every 5 seconds, checks if illustrator is busy, in which case it is still not done with the previous invocation of the illustrator script. If its idle, it runs the script. A bit roundabout, but at least something that works for me!

Thanks for pointing me in the right direction!

#target bridge

var myScript = 'CreateBridgeTalkMessage()';

app.scheduleTask(myScript, 50000, true);

function CreateBridgeTalkMessage() {

    var status = BridgeTalk.getStatus("illustrator");

 

    if(status == "IDLE" || status == 'ISNOTRUNNING')

    {

        var myScript = IllustratorScript.toString() + '\r';

        myScript += 'IllustratorScript();';

        var bt = new BridgeTalk();

        bt.target = "illustrator";

        bt.body = myScript;

        bt.send();

    }

}

function IllustratorScript() {   

   eval(readFile('C:\scripts\illustrator\batchFass.jsx'));

}

The readFile function is like this:

readFile: function(filename) {

        var file = new File(filename);

        file.open('r');

        return file.read();

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Mar 13, 2014 Mar 13, 2014

Glad it was helpful to you and your efforts.

. What version of Illustrator are your using and are you calling that from Illustrator or from natively in the ExtendScript Toolkit?

I ask because I have CS5 and when I run a dumbed down version (seen below) in Illustrator I get "TypeError: app.scheduleTask is not a function", when I run it directly in the ESTK, I don't get the error but yet it does not yield anything either.

#target bridge

var num = 0;

var myScript = 'CreateBridgeTalkMessage()';

app.scheduleTask(myScript, 50000, true);

function CreateBridgeTalkMessage() {

    var status = BridgeTalk.getStatus("illustrator");

    if(status == "IDLE" || status == 'ISNOTRUNNING'){

        var bt = new BridgeTalk();

        bt.target = "illustrator";

        bt.body = "alert(\"Alert_\"+num);";

        bt.send();

    }

    num += 1;

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 13, 2014 Mar 13, 2014

I am using CS5 as well, and running it directly from ESTK. Have yet to try it from illustrator.

I tried your script, and I think there is some issue with the body you are sending. I tried only this:

bt.body = "alert('hello')";

and that worked.

I think the issue is the parameter "num"

I printed the one you were sending, and it was going out to illustrator as

alert("Alert_" + num);

Ilustrator does not know what "num" is, so I tried this:

bt.body = "alert('Alert_'" + num + ")";

It was sending the correct value for num, but illustrator still didn't like it.

So maybe that's something you can play around with?

-Kashmira

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Mar 13, 2014 Mar 13, 2014

Thanks for the feedback. What a shame however that it requires 3 applications (Illustrator/ESTK/Bridge) to all be running just to invoke and use a simple interval. I think using Applescript/VBscript would be less overhead and maybe a cleaner approach myself.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Apr 28, 2014 Apr 28, 2014

Hi,

I needed setInterval functionality and emulated it with the following snippet using app.scheduleTask();

Please note that i programmed with Adobe After Effects as my target application.

Gtlym = new Object();

Gtlym.CALL = new Object();

Gtlym.guid = function() {

     var s4 = function() { return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); };

     return s4() + s4() + s4() + s4()  + s4()  + s4() + s4() + s4();

}

Gtlym.setInterval = function(func,millis){

     this.guid = Gtlym.guid();

     Gtlym.CALL["interval_"+this.guid] = func;

     app.scheduleTask('Gtlym.CALL["interval_'+this.guid+'"]();',millis,true);

}

//Example:

Gtlym.setInterval(function(){/*your code here*/},1000);

Cheers,

Matthias

gentlymad.org - Matthias Guntrum

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 08, 2018 Aug 08, 2018

If you use $.sleep() in ExtendScript then it will block. If you want to create a feature like JavaScript setInterval then you will have to use onIdle event. It triggers on software IDLE time but it there is much more to it. You can check for system state in really short and long amounts of time. It will then return it to you and that is the interval.

Try the sample code:

function main() {
var myIdleTask = app.idleTasks.add({
name: “my_idle_task”,
sleep: 1000
});
var onIdleEventListener = myIdleTask.addEventListener(IdleEvent.ON_IDLE, onIdleEventHandler, false);
}
// SETINTERVAL DOSNT EXIST SO WE USE THE ONLY POSSIBLE WAY ONIDLE EVENT:
function onIdleEventHandler(myIdleEvent) {
var myTextFrames = app.activeDocument.pages.item(0).textFrames;
mimWinPnl.pgr.value +=1;
if(mimWinPnl.pgr.value > 99){ // progress bar value
//Delete idle task by setting its sleep time to zero.
myIdleEvent.parent.sleep = 0;
}
}

I hope it helps you !

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Aug 08, 2018 Aug 08, 2018

That doesn't look like it's for Illustrator.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 08, 2018 Aug 08, 2018

it is not...

...inDesign?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Feb 03, 2019 Feb 03, 2019
LATEST

Just to clarify, you can do this with a simple CEP panel. I don't know of a way to accomplish it with only .JSX, I tried the methods above as a new member and was discouraged since I couldn't get them to reliably work and others above say it's not possible with "JS" though it is as long as you're using CEP and running a simple CSInterface.evalScript function via setInterval.

Apparently Adobe forums doesn't accept text copied from VSCode. When I try to use the standard syntax highlighting feature here, it breaks and just gives me this:

// In CEP while using a Vue CDN:

Vue.component('timer', {

  data() {

   return {

   // Initialize data object for selection:

  selection: {

  timer: null,

  data: null,

  last: null,

  interval: 200,

  }

  }

  },

  mounted() {

   // When component is mounted, start a timer

   this.startTimer(this.selection)

  },

  methods: {

   startTimer(target) { target.timer = setInterval(this.selectionCheck, target.interval); },

   // The timer above runs the below code every 200ms

   selectionCheck() { csInterface.evalScript('scanSelection()', this.selectionRead); },

   // The check above returns a very simple value and calculation, only measuring for change with previous state.

   selectionRead(msg) {

   // If there is a change between this state and previous:

   if (this.selection.last !== msg) {

   // Then assign previous to this state

   this.selection.last = msg;

   // And now we know the state has been changed, use this as the trigger for a larger event.

  } else {

   // Nothing should happen, no change in selection or state.

  }

  }

  }

})

And on the JSX side, the function being called by the timer every 200ms:

function scanSelection() {

   var doc = app.activeDocument;

   var result = [];

   if (doc.pageItems.length) {

   for (var i = 0; i < doc.pageItems.length; i++) {

   var child = doc.pageItems;

   if (child.selected)

   result.push(i);

   }

   }

   if (doc.textFrames.length) {

   for (var i = 0; i < doc.textFrames.length; i++) {

   var child = doc.textFrames;

   if (child.selected)

   result.push(i);

   }

   }

   return result;

}

Which inevitably returns data to the selectionRead function in the original timer. Note that it doesn't have to be the selection count here, you can use a timer to measure any property accessible via scripting in this way, so you can easily create your own custom event listeners via running rudimentary checks.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines