Early Return
Sometimes you need to respond quickly to an incoming HTTP request, and then do other work after sending the response. This makes for snappier UIs for users, and some webhook platforms require responses within a couple seconds. We recommend accomplishing this today by using a queue.
How to set up a queue
In your early-returning HTTP val:
async function handle(request: Request) { // Send off the relevant data a queue HTTP val. // This `fetch` is not awaited. fetch("https://my-queue.web.val.run", { method: "POST", body: req.body, });
// Respond immediately, before the queued work is done return Response.json("ok");}
Your queue is another HTTP val that listens for requests and processes them in their own time. Nobody is waiting for the response from the queue, so it can take as long as it needs to:
async function handle(request: Request) { // Do some work with the request body that takes a long time await doSomeWork(request.body);
return Response.json("ok");}
waitUntil
This technique is a stopgap until full support for waitUntil lands in Val Town, which will handle this case more explicitly.
Promises should otherwise be awaited
While this is a useful technique, it’s important to emphasize that,
in general, you should otherwise await
every Promise.
If you don’t remember to use await
with Promises - besides this
narrow use-case, errors that occur in promises won’t be properly
handled and functions may run out-of-order.
For example, if you use fetch
to request some resource,
but forget to await it, then it won’t throw errors when it fails,
and you won’t have the values you expect to have:
export async function handle() { try { // Result will be an opaque Promise, not a useful value. const result = fetch("https://google.com/"); } catch (e) { // Errors will never be caught here because // fetch is not awaited. handleError(e); }}
HTTP Val Lifecycle
When your HTTP val receives a request, we spin up a process to serve it.
We keep this process alive for some amount of time after the response is sent
to be ready for any other requests that might come its way. After some time of
inactivity, your HTTP process is terminated. This means that if you fire off Promises without awaiting them, they may or may not finish before the val times out, depending on how long they take and whether the val is being kept alive to serve other traffic. The safest path is to await all Promise
s or make yourself a queue.