Detect if a Custom HTML Prompt is Running Asynchronously?

Anyone know if there's a way for a Custom HTML Prompt to know if it's running Asynchronously or not?

I have three ideas.

  • If the user is required to close the Custom HTML Prompt using an HTML button, can't you change a KM variable using the button as the mechanism for KM to tell if the action is still running?
  • Can't you fetch the list of processes and see if there are any Custom HTML processes running?
  • Can't you use a Find Image action to see if part of the Custom HTML Prompt window is still present on the screen?

But aren't you the person with the honorary Ph.D. in KM?

Nope. That ain't me. Bachelors, maybe. :joy:

I've discovered the best answer for my specific use case:

Here's what I wanted to do, which I am now in the process of coding: I wanted to run my Custom HTML Prompt two ways. The normal mode is synchronously, and everything is hunky-dory.

But I also wanted to be able to run it asynchronously, in which case it would act differently. This is not a normal occurrence, so I'm perfectly happy with setting a variable telling the prompt that it's running async.

But if it's running async, the prompt can't access local variables, which means I'd have to use a global variable, and I really didn't want to do that. (In fact, I'm in the process of cleaning up my KM variables, and this prompt will help with that, so no way was I going to add to the mess if I could help it!)

It turns out that even if the prompt is running async, Peter fills document.kmvar with all variables, including local ones. So all I have to do is something like this:

if (document.kmvar && document.kmvar.Local_ViAllVariables === "1")

The first check to see if document.kmvars is truthy probably isn't needed, but it doesn't hurt.

See Custom HTML Prompts :: Variable Value at Launch Time vs Value Now - #2 by DanThomas


I knew you probably wanted "the right way" to solve your problem. But I always like to show alternate ways.

1 Like

and another Boolean expression might be:

"Local_ViAllVariables" in (document.kmvar || {})

You could generalize a bit, of course, but it would still depend on there actually being a Local_ to look for ...

Object.keys(document.kmvar || {})
    k => k.toLocaleLowerCase().startsWith("local")
1 Like

that's a good find to know that document.kmvar stores those 'local km variable'
It makes me wonder why Peter didn't simply design KM.GetVariable to obtain from document.kmvar instead. I think that because Peter want to keep the concept of Local variable consistent which if the macro has completed execution, the Local variable should not exist. So whatever store in document.kmvar has become global variable (eg local_ or Local_ variable is just a name of property, nothing to do with KM anymore )

From what I know, this is what happen. When custom HTML prompt window is run asynchronously, and getting data from Local km variable eg Local_inputJson, Local_inputJson will be empty (go out of scope) because before the prompt has the chance to read it, the macro to which Local_inputJson belong to has completed. This is confirmed by adding a Pause action after Custom Prompt action with a delay long enough for the prompt to read it.

So as what has been mentioned in this thread , one way is to override GetVariable with
window.KeyboardMaestro.GetVariable = (variable) => document.kmvar[variable];

// Assuming that document.kmvar store all local_variables to keep thing simple .


[EXP] Async Prompt.kmmacros (2.5 KB)

So going forward, i going to replace global variables that exist just to pass data to async custom prompt with local variables, while overriding GetVariable

thank for the finding.

One thing to remember when using document.kmvar is that you may not be getting the most recent value of the variable. This is fine at the start of the prompt. But if the prompt runs for any length of time, then variable values could change, but document.kmvar is static. So I don't think overriding GetVariable is necessarily a good thing to do, at least not all the time.

Another issue with document.kmvar is that there are times when it doesn't match what you'd get with, say, using AppleScript to get all the variables. I've seen times where I've deleted a variable, then launched a custom prompt and document.kmvar still shows the variable, and its old value. But AppleScript thinks it's deleted. I don't have all the details for this, but it definitely happens. I saw it happen earlier today, in fact.

thank for information.
That left me thinking what is the best way to pass local variable to async custom prompt given document.kmvar may not be reliable. Currently I just using a global variable to pass it to async custom prompt and then clear it once read. Maybe one day Peter may add explicit parameter passing to custom prompt (just like subroutine) ?

Actually, I think you can rely on document.kmvar for passing a local variable to an async custom prompt.

All I was saying is that sometimes it's not completely reliable for global variables that are deleted, or at least should be. And that it won't reflect variables whose values change after the prompt starts up.

1 Like

Or to put it another way, perhaps – an entirely reliable snapshot of the variable state at action launch, but no picture at all of variable state later on.

1 Like

I see. Noted.

@peternlewis Is there a way for a Custom HTML Prompt to know if it's running Asynchronously or not?

Not that I can think of.

1 Like

You could always cheat, for example, by passing the character "~" somewhere in the title of the Custom HTML Prompt action, and the Javascript could (I suspect) fetch that title and see if there's a "~" in there, which would mean it was called asynchronously.

In physics we call this "hidden variables". There are no hidden variables in quantum physics (so far as we know) but there certainly can be hidden variables in Keyboard Maestro.

Nice idea, but it's no different than what I have now. I already pass a variable to tell the prompt it's running async, but there's no guarantee that the variable will match how the prompt was actually executed. The same is true of the title.

Okay. The only Ph.D. I have is "Piled High and Deep" so my advice isn't always good. Especially when talking to someone with a real Ph.D.

I had a friend, who actually was a Ph.D., and he said that all the time. Funny,

And quit apologizing! :joy:

1 Like

But I'm Canadian. Apologizing is like saying "Eh!" We've got more apologies in us than we have maple syrup.

But we Canadians will never apologize for the events of 1812, when America invaded Canada but soldiers from Canada fought back and captured the capital of America, and then, to add insult to injury, burned down the White House. The country of Canada was not officially formed until 1867, so you could argue we were British, not Canadian, but two of the provinces were called Canada at the time, so in my mind we were Canadians. And we have never apologized for conquering America's capital... and capitol.

1 Like

LOL. As for the rest, I know you were kidding - at least I think you were, but let's leave politics out of this forum, even in jest. It's a can of worms (I was going to say "bag of worms" which I think is funnier) we don't want to open.


Sorry, I wasn't trying to be political, just humorous. Although the facts as I offered them are actually true. Not many people know Canada conquered America's capital.