Hi @chrscheuer
I've read through the information and reading other threads, i can see how to handle errors within a function's code but it's not clear how to handle errors when calling a function.
I have a situation where the function is quite long and convoluted. There are a few errors that seem to get thrown up randomly. Running the script again often solves the issues. Ideally I'd like to be able to call the function as many times as needed until there are no errors. It would also be ideal if the error could be logged in console for inspection.
Something that looks like this would be ideal:
function keepAttemptingToBounceStem() {
while (true) {
if (bounceStem().success) {
break;
}
}
}
Thanks!
Linked from:
- Christian Scheuer @chrscheuer2022-08-06 12:16:42.142Z
You could use a try/catch block for this. Don't add the ".success" here, that's only available for SF action calls.
The try/catch block method is discussed in the article I referred to - but it's a normal Javascript structure so you could find it in any Javascript documentation :)
https://help.soundflow.org/en/articles/5638002-error-handling-in-soundflow-scripts
Christian Scheuer @chrscheuer2022-08-06 12:18:47.401Z
Example:
function keepAttemptingToBounceStem() { while (true) { try { bounceStem(); //Success, so break out of the loop break; } catch (err) { //An error occurred. Wait for some time, then try again (continuing the while loop) sf.wait({ intervalMs: 2000 }); } } }
Christian Scheuer @chrscheuer2022-08-06 12:19:16.238Z
Note that I'd generally recommend using a for loop instead of a while loop, to limit the number of retries to a set amount instead of it being infinite.
Christian Scheuer @chrscheuer2022-08-06 12:21:07.344Z
Here I've refactored the retry algorithm out into a separate function so you can reuse the logic :)
function retry({action, intervalMs, numberOfTries}) { for(var i=0; i<numberOfTries; i++) { try { action(); //Success, so break out of the loop break; } catch (err) { if (i === numberOfTries - 1) { throw `We tried ${numberOfTries} times, but failed every time`; } //An error occurred. Wait for some time, then try again (continuing the while loop) sf.wait({ intervalMs: intervalMs }); } } } retry({ action: () => bounceStem(), intervalMs: 2000, numberOfTries: 10, });
- AAlex Oldroyd @Alex_Oldroyd8
Amazing!! Thanks, @chrscheuer !! This is exactly what I was after!!
- In reply tochrscheuer⬆:TTristan Hoogland @Tristan
Heya @chrscheuer
Thanks for this script! I've been using it as a means to try circumvent "filename already exists" and add an integer when doing bounces in protools. My only issue is that for whatever reason, it's only retrying the process once for me. I.e. Bounce Name_10, retry _11, retry_12 and stops there. Adjusting the numberOfTries doesn't seem to change anything on my end.
If I copy and paste the final 5 lines of that little retry section (i.e. below), it attempts it several more times (depending how many times I've copied and pasted that little snippet in a row).
sf.ui.proTools.windows.whoseTitle.is("Bounce Mix").first.buttons.whoseTitle.is("Bounce").first.elementClick(); function bounceAlreadyExists() { var alreadyExistsConfirmDlg = sf.ui.proTools.confirmationDialog; if (alreadyExistsConfirmDlg.exists) { alreadyExistsConfirmDlg.elementWaitFor({ waitType: 'Appear' }); alreadyExistsConfirmDlg.buttons.whoseTitle.is("No").first.elementClick(); alreadyExistsConfirmDlg.elementWaitFor({ waitType: 'Disappear' }); //Find the first text field var existingFileName = sf.ui.proTools.windows.whoseTitle.is("Bounce Mix").first.textFields.first; //Get the current Name var currentName = existingFileName.value.value; //Create a new name (get the name and suffixed number - if your session name was 'My Session 42' then save 'My Session ' in grps[1] and '42' in grps[2]) var grps = currentName.match(/^(.+?)(\d+)$/); //Construct a new name based on the prefix and the number (+1), followed by the '.ptx' suffix. If there was no number, just add '.01' var newNumber = !grps || grps.length === 0 || isNaN(Number(grps[2])) ? ' 01' : ((Number(grps[2]) + 1) + '').padStart(2, '0'); var newName = (grps ? grps[1] : (currentName)) + newNumber; //Set the value of the textField existingFileName.elementSetTextFieldWithAreaValue({ value: newName }); sf.ui.proTools.windows.whoseTitle.is("Bounce Mix").first.buttons.whoseTitle.is("Bounce").first.elementClick(); } } bounceAlreadyExists(); function retry({action, intervalMs, numberOfTries}) { for(var i=0; i<numberOfTries; i++) { try { action(); //Success, so break out of the loop break; } catch (err) { if (i === numberOfTries - 1) { throw `We tried ${numberOfTries} times, but failed every time`; } //An error occurred. Wait for some time, then try again (continuing the while loop) sf.wait({ intervalMs: intervalMs }); } } } retry({ action: () => bounceAlreadyExists(), intervalMs: 2000, numberOfTries: 10, }); retry({ action: () => bounceAlreadyExists(), intervalMs: 2000, numberOfTries: 10, }); retry({ action: () => bounceAlreadyExists(), intervalMs: 2000, numberOfTries: 10, }); retry({ action: () => bounceAlreadyExists(), intervalMs: 2000, numberOfTries: 10, }); retry({ action: () => bounceAlreadyExists(), intervalMs: 2000, numberOfTries: 10, }); retry({ action: () => bounceAlreadyExists(), intervalMs: 2000, numberOfTries: 10, });
Christian Scheuer @chrscheuer2022-10-15 08:19:06.578Z
The retry function only retries if there's an exception caught. Were you trying to get this to just double check the filename so it won't overwrite with an invalid name?
For that, it would be better to read the contents of the audio files folder and come up with a unique name instead.
- TTristan Hoogland @Tristan
Thanks @chrscheuer !
That’s exactly what I’m trying to do. The user is prompted and enters a mix name, stored as a globalState variable and so entering the same bounce name, while unlikely is possible. I’m trying to get it so in the event protools reports back a duplicate/overwrite prompt, it re-reads the textfield value and increments the file name.
Your suggestion does make more sense and would incur a lot less issues with multiple prompts so I’ll try that. If you have any immediate scripts handy for that that you could share that’d be great! Otherwise I’ll dig around later and see what I can accomplish on my own.
Christian Scheuer @chrscheuer2022-10-15 19:42:49.069Z
Use
sf.file.exists(( path: ' ... ' }).exists
to check if a file exists :)- In reply tochrscheuer⬆:TTristan Hoogland @Tristan
wow and after hours of scratching my head, then posting this, 2 minutes later I figured it out. Thanks!