Home > Back-end >  Is it possible to tell if an async function is currently running at the top of the "program&quo
Is it possible to tell if an async function is currently running at the top of the "program&quo

Time:05-27

I'm trying to do something that involves a global context that knows about what function is running at the moment.

This is easy with single-threaded synchronous functions, they start off running and finish running when they return.

But async functions can pop to the bottom of the program and climb back up multiple times before completing.

let currentlyRunningStack: string[] = [];
function run(id: string, cb: () => any) {
  currentlyRunningStack.push(id);
  cb()
  currentlyRunningStack.shift();
}

// works with synchronous stuff
run("foo", () => {
  run("bar", () => console.log("bar should be running"));
  console.log("now foo is running");
});

// can it work with asynchronous
run("qux", async () => {
  // async functions never run immediately...
  await somePromise();
  // and they start and stop a lot
});

Is it possible to keep track of whether or not an asynchronous function is currently running or currently waiting on something?


EDIT: there appears to be something similar called Zone.js. Used by Angular I guess.


EDIT: per @Bergi's suggestion, the word "stack" has been updated to "program" for clarification

CodePudding user response:

It is possible, and someone has done it -- the angular developers, no less -- but it costs a whopping 5.41Mb!!

https://www.npmjs.com/package/zone.js

This was ripped from this very similar question: Something like async_hooks for the browser?

In order to distinguish from that question a bit, I'll answer the core query here:

Yes, you can tell when an async function stops and starts. You can see a lot of what's required in the project code

In particular, this file appears to handle poly-filling promises, though I'd need more time to verify this is where the magic happens. Perhaps with some effort I can distill this into something simpler to understand, that doesn't require 5.41 Mb to acheive.

CodePudding user response:

Yes, it possible.

Using a running context, like a mutex, provided by Edgar W. Djiskistra, and Observers, proposed by the Gang of Four and Promise.all, you can keep track if there's a running function in the program. You will have to implement a garbage collector, keeping the mutex list clean and will need a timer to verify if the context is clean. When the context is clean, you will call a callback-like function to end you program, like process.exit(0).


Some techniques will need to be used, like a functor (a function pointing to result), type checking (if is whether a promise or not to transform), promosification (transforming every function into a promise) , mutex and applicatives.

Transforming the functor into a applicative with an callback to the emitter of the observer to clean the cache or/and handle errors(avoiding it or logging it) or provoking side effects and calling the next without needing to do a recursion which will provoke a max depth call stack error, therefore JS doesn't have tail call optimization on the code level and interpreter level. Finally, on the rest, the collector cares it all.

The timer will do the end of the program and there's it. You can keep track if a function is running or not and have every function registered running in a syncrhonous manner using await with and mutex.


Obs: Some concepts can be difficult but have a lot of material in the web, like functors and applicatives.

  • Related