Top level await when?

When can we expect support for top level await be added to Workers?

Support in v8 was merged a couple weeks ago.

We probably won’t add support for this in Workers.

In the Workers platform, it is intentionally left unspecified when, exactly, the top-level scope executes. It might execute on-demand right before handling a request. Or, it might run in advance, to pre-warm the worker before requests arrive. It might execute on every machine that loads the worker. Or, it might execute just once, and then a “snapshot” of the worker state might be distributed to multiple machines to run multiple instances based on that one startup.

It’s important to us that we can change how we do these things over time without potentially breaking workers that depend on particular behavior. Because of this, we do not want the top-level scope to do anything that isn’t self-contained and deterministic. It’s important that two executions of the top-level scope produce exactly the same worker state.

It’s also important that the top-level scope executes quickly, because it may be executed on-demand when a request has already arrived. If the top-level scope were to perform network requests, those network requests would create extra latency for the user who is already waiting.

With that said, I’d love to know more about what you were hoping to do with await in the top-level scope, so that we can figure out if there’s some other feature we could provide that solves the problem.

6 Likes

I’ve been wanting to use top level awaits for things like crypto.subtle.importKey, where values are predetermined, but the API returns a promise.

Right now, I’m using a function that caches the result in a global variable after the first call, but that’s a little unwieldy and I think it may have a chance of being run more than once before it gets cached.

I could also see a use case where I want to go through an oauth flow to get a token that could be reused.

Thanks for the feedback!

We actually have some better solutions coming for these specific issues. I can’t give a timeline but we’re working on it.

1 Like

Are you able to share what the actual solution looks like, regardless of timeline.

It would look like the recently-added secrets support, except that you could declare a secret of type CryptoKey, and the binding would end up containing an already-instantiated CryptoKey object when the script starts.

FWIW, though, importKey is a cheap function so calling it on every request probably isn’t a big deal.