Does top-level await have a timeout?

467 Views Asked by At

With top-level await accepted into ES2022, I wonder if it is save to assume that await import("./path/to/module") has no timeout at all. Here is what I’d like to do:

// src/commands/do-a.mjs

console.log("Doing a...");
await doSomethingThatTakesHours();
console.log("Done.");
// src/commands/do-b.mjs

console.log("Doing b...");
await doSomethingElseThatTakesDays();
console.log("Done.");
// src/commands/do-everything.mjs

await import("./do-a");
await import("./do-b");

And here is what I expect to see when running node src/commands/do-everything.mjs:

Doing a...
Done.
Doing b...
Done.

I could not find any mentions of top-level await timeout, but I wonder if what I’m trying to do is a misuse of the feature. In theory Node.js (or Deno) might throw an exception after reaching some predefined time cap (say, 30 seconds).

Here is how I’ve been approaching the same task before TLA:

// src/commands/do-a.cjs
import { autoStartCommandIfNeeded } from "@kachkaev/commands";

const doA = async () => {
  console.log("Doing a...");
  await doSomethingThatTakesHours();
  console.log("Done.");
}

export default doA;

autoStartCommandIfNeeded(doA, __filename);
// src/commands/do-b.cjs
import { autoStartCommandIfNeeded } from "@kachkaev/commands";

const doB = async () => {
  console.log("Doing b...");
  await doSomethingThatTakesDays();
  console.log("Done.");
}

export default doB;

autoStartCommandIfNeeded(doB, __filename);
// src/commands/do-everything.cjs
import { autoStartCommandIfNeeded } from "@kachkaev/commands";
import doA from "./do-a";
import doB from "./do-b";

const doEverything = () => {
  await doA();
  await doB();
}

export default doEverything;

autoStartCommandIfNeeded(doEverything, __filename);

autoStartCommandIfNeeded() executes the function if __filename matches require.main?.filename.

2

There are 2 best solutions below

0
On BEST ANSWER

Answer: No, there is not a top-level timeout on an await.

This feature is actually being used in Deno for a webserver for example:

import { serve } from "https://deno.land/[email protected]/http/server.ts";

const server = serve({ port: 8080 });
console.log(`HTTP webserver running.  Access it at:  http://localhost:8080/`);

console.log("A");

for await (const request of server) {
  let bodyContent = "Your user-agent is:\n\n";
  bodyContent += request.headers.get("user-agent") || "Unknown";

  request.respond({ status: 200, body: bodyContent });
}

console.log("B");

In this example, "A" gets printed in the console and "B" isn't until the webserver is shut down (which doesn't automatically happen).

0
On

As far as I know, there is no timeout by default in async-await. There is the await-timeout package, for example, that is adding a timeout behavior. Example:

import Timeout from 'await-timeout';
 
const timer = new Timeout();
try {
  await Promise.race([
    fetch('https://example.com'),
    timer.set(1000, 'Timeout!')
  ]);
} finally {
  timer.clear();
}

Taken from the docs: https://www.npmjs.com/package/await-timeout

As you can see, a Timeout is instantiated and its set method defines the timeout and the timeout message.