Forum for the PDF-XChange Editor - Free and Licensed Versions
Moderators: PDF-XChange Support , Daniel - PDF-XChange , Chris - PDF-XChange , Sean - PDF-XChange , Paul - PDF-XChange , Vasyl - PDF-XChange , Ivan - Tracker Software , Stefan - PDF-XChange
Mathew
User
Posts: 586 Joined: Thu Jun 19, 2014 7:30 pm
Post
by Mathew » Sat Apr 05, 2025 4:16 pm
When using the new app.setInterval with a function parameter that encloses app.clearInterval, the application will crash after the interval is cleared.
To reproduce, run in the console:
Code: Select all
{
let intervalTimer = new Date ();
let interval = app.setInterval( function testInterval ( ) {
let stopTimer = (new Date () - intervalTimer) > 5 * 1000 ;
if (stopTimer) {
app.clearInterval(interval);
if ( 4 === app.alert({cMsg :"Do you need more time?" , nIcon : 2 , nType : 2 })) {
intervalTimer = new Date ();
interval = app.setInterval( testInterval, 500 );
}
}
console .println('click...' + Math .ceil(10 - (new Date () - intervalTimer)/500 ));
}, 500 );
}
The application (builds 393 and 394) crashes every time I press "Cancel".
Workaround
My current workaround is a recursive setTimeOut.
Daniel - PDF-XChange
Site Admin
Posts: 11117 Joined: Wed Jan 03, 2018 6:52 pm
Post
by Daniel - PDF-XChange » Mon Apr 07, 2025 4:55 pm
Hello, Mathew
Thank you for the report, I have reproduced this in build 395 as well, and passed it along to the Dev team for review.
Kind regards,
Dan McIntyre - Support Technician
PDF-XChange Co. LTD
+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com
Roman - Tracker Supp
Site Admin
Posts: 334 Joined: Sun Nov 21, 2004 3:19 pm
Post
by Roman - Tracker Supp » Tue Apr 08, 2025 8:12 pm
Hi Mathew,
The bug has been fixed for the upcoming v10.6 release of the Editor.
Roman - Tracker Supp
Site Admin
Posts: 334 Joined: Sun Nov 21, 2004 3:19 pm
Post
by Roman - Tracker Supp » Wed Apr 09, 2025 6:26 pm
Mathew, you might find it suitable to use this utility class:
Code: Select all
class AsyncIntervalGenerator {
constructor (t) {
this .count = 0 ;
this .interval = app.setInterval(
() => this .resolve({value : this .count++, done : false }),
t
);
}
next() {
return new Promise ((resolve ) => this .resolve = resolve);
}
return () {
app.clearInterval(this .interval);
return Promise .resolve({value : undefined , done : true });
}
[Symbol .asyncIterator]() {
return this ;
}
}
It will allow to simplify your interval related code. For example:
Code: Select all
async function doIntervalWork ( ) {
for await (const i of new AsyncIntervalGenerator(500 )) {
if ((i + 1 ) % 10 == 0 ) {
if ( 4 !== app.alert({cMsg :"Do you need more time?" , nIcon : 2 , nType : 2 }))
break ;
}
console .println(`${i + 1 } bits of work` );
}
return 'Done' ;
}
doIntervalWork().then((status ) => console .println(`Finished with status '${status} '` ));
console .println('Started' );
Or, if you want to completely separate the interval management logic from the actual payload, you can split the doIntervalWork function like this:
Code: Select all
async function * workIntervals ( ) {
for await (const i of new AsyncIntervalGenerator(500 )) {
if ((i + 1 ) % 10 == 0 ) {
if ( 4 !== app.alert({cMsg :"Do you need more time?" , nIcon : 2 , nType : 2 }))
break ;
}
yield i;
}
}
async function doIntervalWork ( ) {
for await (const i of workIntervals()) {
console .println(`${i + 1 } bits of work` );
}
}
Mathew
User
Posts: 586 Joined: Thu Jun 19, 2014 7:30 pm
Post
by Mathew » Wed Apr 09, 2025 7:34 pm
Thanks for that Roman! I'm just starting to get my head around async functions. This is really helpful.
Roman - Tracker Supp
Site Admin
Posts: 334 Joined: Sun Nov 21, 2004 3:19 pm
Post
by Roman - Tracker Supp » Wed Apr 09, 2025 8:32 pm
You are welcome!
Roman - Tracker Supp
Site Admin
Posts: 334 Joined: Sun Nov 21, 2004 3:19 pm
Post
by Roman - Tracker Supp » Wed Apr 09, 2025 9:32 pm
By the way, the Editor supports a few extensions to Adobe JS API that facilitate Javascript async features.
For example,
global.changed :
Code: Select all
async function monitorGlobal (varName ) {
try {
for (;;) {
const newValue = await global.changed(varName);
console .println(`New value for ${varName} : ${newValue} ` );
}
} catch {
console .println(`${varName} deleted` );
}
}
if (app.doc) {
monitorGlobal('v1' ).then(() =>console .println('Monitoring completed' ));
app.setTimeOut('global.v1=1;' , 1 );
app.setTimeOut('global.v1=2;' , 1000 );
app.setTimeOut('delete global.v1;' , 2000 );
}
Another is
app.timeOut .