Copy link to clipboard
Copied
Hello;
I have a script that pols a folder for files despited by some other process (getDataFiles()); when it finds a file, it processes it (processData()), then moves it to a different folder and pols for a newly depostied file. This is the loop you see below.
I’m looking for a way to break the loop. I can’t, from what I’ve read, set the “isStopped” variable via a button click because of the single-thread nature of Javascript processing.
Ideally, I’d like to have a UI with a start and stop button.
I’ve spent a lot of time Googling, to no avail. What would you suggest?
Thanks.
var isStopped = false;
...
...
...
function doIt() {
while (!isStopped) {
getDataFiles(); // read the file names into var dataFiles
for(i=0; i < dataFiles.length ;i++) { // if there are files,process them.
processData(dataFiles[i].name)
}
// wait for a bit (for new data files to be deposited)
$.sleep(2000) // wait 2 seconds
} // while !isStopped
}
2 Correct answers
Unfortunately, Ae scripting has no concept of code running asynchronous. That means while your code is running, Ae essentially freezes and hence the user has no chance to click a button.
For anything that goes beyond a simple progress bar, I recommend to implement that as a CEP panel instead.
In CEP you can write asynchronous javascript such that the UI stays fully responsive while your file processing operations run in the background.
Instead of having one function "startProcessing()" that does all the work, you need to have a function that only does a little bit of processing and then returns to give the user the chance to cancel. The evalScript has a second parameter: a function that is called when the evalScript finished. Use it to start the next bit of work.
Example:
Say you have to process each layer from 1 to 100 of a composition in whatever way. Then you could do it like this:
var firstLayer = 1;
var lastLayer = 100;
...
Copy link to clipboard
Copied
Unfortunately, Ae scripting has no concept of code running asynchronous. That means while your code is running, Ae essentially freezes and hence the user has no chance to click a button.
For anything that goes beyond a simple progress bar, I recommend to implement that as a CEP panel instead.
In CEP you can write asynchronous javascript such that the UI stays fully responsive while your file processing operations run in the background.
Copy link to clipboard
Copied
Thank you for your quick response Mathias; it does seem like AE scripting is fire-and-forget 😉
I've downloaded a few tutorials on CEP and will start learning about it this evening.
Kind regards,
Roland
Copy link to clipboard
Copied
Yes. Little side note: Adobe plans to discontinue CEP in the longterm and replace it with UXP. UXP is not yet available for After Effects, so for now CEP is your only option. But when learning CEP keep in mind that you will have to port your tools to UXP in the long term.
Copy link to clipboard
Copied
Hi Mathias; OK, I’ve created my first panel with start and stop buttons.
I’ve moved the loop to the JS from the JSX; still no luck stopping the loop, I tried a couple of things; likely for the same reason as my previous attempt.
What is your recommendation please, thanks so much for your help.
var csInterface = new CSInterface();
var isStopped = false;
var startButton = document.querySelector("#start-button");
startButton.addEventListener("click", startProc); /* Write a helper function to pass instructions to the ExtendScript side. */
var stopButton = document.querySelector("#stop-button");
stopButton.addEventListener("click", stopProc); /* Write a helper function to pass instructions to the ExtendScript side. */
function startProc() {
while (!isStopped) {
csInterface.evalScript("startProcessing()");
}
}
function stopProc() {
isStopped == true;
}
Copy link to clipboard
Copied
Instead of having one function "startProcessing()" that does all the work, you need to have a function that only does a little bit of processing and then returns to give the user the chance to cancel. The evalScript has a second parameter: a function that is called when the evalScript finished. Use it to start the next bit of work.
Example:
Say you have to process each layer from 1 to 100 of a composition in whatever way. Then you could do it like this:
var firstLayer = 1;
var lastLayer = 100;
function startProc(){
doWorkForLayer(firstLayer);
}
function doWorkForLayer(nextLayerToBeProcessed){
csInterface.evalScript("processLayer(${nextLayerToBeProcessed})", function(){
// this code is executed once processLayer is finished
if(!isStopped && nextLayerToBeProcessed<= lastLayer ){
doWorkForLayer(nextLayerToBeProcessed+1)
}
});
}
Copy link to clipboard
Copied
Ahhhhhh, thank you again Mathias! That did it. One little thing trippped me up, especcialy because it results in a weird error message, "unable to execute script at line 1: Expected: )":
"processLayer(${nextLayerToBeProcessed})"
must be in 'accent grave' characters:
`startProcessing(${nextLayerToBeProcessed})`

