A Question, and a Potential Request

@peternlewis Consider the following:

image

Question: Can I assume that at least one of the two magenta actions will always get executed, assuming the macro doesn't get killed by some external process (i.e. "Cancel All Macros")?

Potential request: It's probably obvious, but I'd still like to have a "finally". However, if the answer to the "Question" is "yes, I can assume at least one of the actions will get executed", then I suppose it's not really necessary, although the programmer in me doesn't like not having a "finally". :roll_eyes:

Thanks.

1 Like

Hi Dan,
Having "finally" is good.

In the meantime, this may work for you. Force a throw action regardless . This will ensure whether error happen or not, it still invoke "Close Animated Gif"

1 Like

Yes, one or other should run every time.

However you'd get the same result by moving a single copy of the purple action after the Try/Catch and removing the two existing ones, which is why I don't see the need to a Finally clause. Anything that would work in the case above, or with Finally, would also work with the action placed immediately after the Try/Catch action.

OK, I gave a bad example, because I hadn't thought through the implications of the "Catch" portion of the Try/Catch.

Here's your suggestion (I think, let me know if I'm wrong):

image

What happens if I click the "Cancel" button in the Prompt (red action)? In this case, it means I want to cancel the macro. But since it's inside the Try/Catch, it won't cancel the macro.

So yes, the magenta Close action will execute. But the code after that (the yellow Notification) will also execute, which is not what I wanted - I wanted to cancel the macro.


So in fact, the only safe way to code it with a Try/Catch is like this:

image

Am I wrong?

Yes, that looks correct.

And I don't see how a Finally section would help in that case. Because if the Finally section was going to run, then it would continue on to the actions afterwards, so that is not what you want anyway (and would still be equivalent to placing your Finally code after the Try/Catch action.

No, that's not how Try/Finally works.

Try/Finally with Error in the Try Section

The "After try/finally" console message does not get displayed.

try {
	console.log("Starting");
	throw new Error("Example error");
} finally {
	console.log("Finally");
}
console.log("After try/finally");

Result:

/* Starting */
/* Finally */

Result:
Error -2700: Script error.

NOTE: If you run the script in Script Editor, don't forget to have it show the "Replies":

image

So, for our Prompt code, this guarantees that the prompt gets closed no matter that else happens, but it still aborts if there's an error:

try {
	showPrompt();
	throw new Error("Example error");
} finally {
	closePrompt();
}
console.log("After try/finally");

Here's some other examples, which will answer some questions I'm guessing you might have:

Baseline Case with No Errors

Nothing surprising here, but I included this to be complete.

try {
	console.log("Starting");
} finally {
	console.log("Finally");
}
console.log("After try/finally");

Result:

Starting
Finally
After try/finally

Try/Finally with Return

In KM, the "return" could also be something like "Cancel Macro". Again, the "After try/finally" console message does not get displayed.

tryFinallyWithReturn();

function tryFinallyWithReturn() {
	try {
		console.log("Starting");
		return "Exiting";
	} finally {
		console.log("Finally");
	}
	console.log("After try/finally");
}

Result:

/* Starting */
/* Finally */

Result:
"Exiting"

Try/Finally with Error, and Error in Finally

The error message from the error in the Try section gets eaten, replaced with the error message from the error in the Finally section

try {
	console.log("Starting");
	throw new Error("Example error");
} finally {
	console.log("Finally");
	throw new Error("Finally error");
}
console.log("After try/finally");

NOTE: You can't see the results clearly in Script Editor, so I'm showing the results from VSCode, slightly edited to remove fluff.

Result:

Starting
Finally
Error: Finally error (-2700)

NOTE: I usually try to avoid this at all costs, because it hides the real cause of the error. So if I think there's a chance the code in the Finally section could generate an error, I wrap it in a Try/Catch and eat the error:

try {
	console.log("Starting");
	throw new Error("Example error");
} finally {
	try {
		console.log("Finally");
		throw new Error("Finally error");
	} catch {
	}
}
console.log("After try/finally");

Try/Catch/Finally Baseline

Nothing unexpected here, other than the "Catch" eats the error.

try {
	console.log("Starting");
	throw new Error("Example error");
} catch (e) {
	console.log("Catch caught this error: " + e.message);
} finally {
	console.log("Finally");
}
console.log("After try/finally");

Result:

Starting
Catch caught this error: Example error
Finally
After try/finally

Try/Catch/Finally with Errors

Since the Finally section throws an error, it overrides the errors from the Try and the Catch section.

try {
	console.log("Starting");
	throw new Error("Example error");
} catch (e) {
	console.log("Catch caught this error: " + e.message);
	throw e;
} finally {
	console.log("Finally");
	throw new Error("Finally error");
}
console.log("After try/finally");

Result:

Starting
Catch caught this error: Example error
Finally
Error: Finally error (-2700)

Conclusion:

This is the way Try/Finally has worked in every language I've ever used it in.

This is a Ph.D. level reply. And you are braver than a Navy Seal for taking on the Architect.