vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.4k stars 26.9k forks source link

[NEXT-1318] Unable to use context.waitUntil in Route Handler? #50522

Open s1973 opened 1 year ago

s1973 commented 1 year ago

What is the improvement or update you wish to see?

When using pages router, we can use context on api routers:

import { NextResponse } from 'next/server';
import type { NextFetchEvent, NextRequest } from 'next/server';

export const config = {
  runtime: 'edge',
};

const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

async function getAlbum() {
  const res = await fetch('https://jsonplaceholder.typicode.com/albums/1');
  await wait(10000);
  return res.json();
}

export default function MyEdgeFunction(
  request: NextRequest,
  context: NextFetchEvent,
) {
  context.waitUntil(getAlbum().then((json) => console.log({ json })));

  return NextResponse.json({
    name: `Hello, from ${request.url} I'm an Edge Function!`,
  });
}

while using app router, we got this from doc:

Currently, the only value of context is params, which is an object containing the dynamic route parameters for the current route.

so I am wondering how to use NextFetchEvent with route handler?

Is there any context that might help us understand?

I am trying to keep the function running after a response has been sent, as the vercel doc navigated, we can use waitUntil(), but it seems not approachable in App Router and Route Handler, can I get any thoughts? thanks

Does the docs page already exist? Please link to it.

https://nextjs.org/docs/app/api-reference/file-conventions/route#context-optional

NEXT-1318

oalexdoda commented 1 year ago

Hey @s1973 have you managed to figure this out yet?

oalexdoda commented 1 year ago

@balazsorban44 is this a Next.js bug? And if so, any estimate as to when context.waitUntil would become available?

balazsorban44 commented 1 year ago

Hi, it's more like a missing feature. when Route Handlers have been introduced this was not added to the initial implementation requirements.

But after some internal discussions, we think we should add it so there's feature parity with API Routes (edge).

It's now tracked internally.

oalexdoda commented 1 year ago

Hi, it's more like a missing feature. when Route Handlers have been introduced this was not added to the initial implementation requirements.

But after some internal discussions, we think we should add it so there's feature parity with API Routes (edge).

It's now tracked internally.

Got it. Thank you! Will keep an eye out since it's blocking us from migrating some pretty important routes to the app directory.

oalexdoda commented 1 year ago

Hey @balazsorban44 , is this being worked on yet by any chance? If so can I have a rough ETA? Thank you & I really appreciate it!

raunakdoesdev commented 1 year ago

+1 on this

Kind of strange that this was released without this feature. The types are literally wrong in saying there is this property that doesn't exist (waitUntil). Had to move some routes to page router as a result of it.

kyb3r commented 1 year ago

Any updates on this?

anuraagvaidya commented 1 year ago

+1 on this

Kind of strange that this was released without this feature. The types are literally wrong in saying there is this property that doesn't exist (waitUntil). Had to move some routes to page router as a result of it.

Were you able to access the context object using page router? Mine is an empty object.

anuraagvaidya commented 1 year ago

I was able to get around this issue by moving my long-running functions to middleware.js

export async function middleware(req, context) {
    if(/*match your path*/)
    {
        context.waitUntil(callFunctionsThatReturnsPromise);
    }
}
oalexdoda commented 1 year ago

Great workaround @anuraagvaidya , but pretty inconvenient for large apps with lots of moving pieces & routes. Really hoping to see native context support at a route level

matannahmani commented 10 months ago

any updates on this?

Edit by maintainers: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

sam3d commented 10 months ago

The Next.js team has created an undocumented (and highly experimental) API for this: internal_runWithWaitUntil.

⚠️ This is an internal API and will be removed soon. Please do not use.

"use server";

import { internal_runWithWaitUntil as waitUntil } from "next/dist/server/web/internal-edge-wait-until";

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

export async function action() {
  console.log("Request received");

  waitUntil(async () => {
    await sleep(10000);
    console.log("Waited for 10 seconds");
  });

  return "Returned immediately";
}
maccman commented 8 months ago

@sam3d I'm wondering if there's an update on when this is being planned to be released?

PSoltes commented 7 months ago

Yeah feels weird that there were 2(!!) major versions with app router released without this kinda important feature.

kyb3r commented 6 months ago

using internal_runWithWaitUntil

But any eta when the api will be stabilised in a release?

maccman commented 5 months ago

It's brewing! https://github.com/vercel/next.js/pull/65038

Thinkscape commented 5 months ago

Good news!

https://vercel.com/changelog/waituntil-is-now-available-for-vercel-functions https://vercel.com/docs/functions/functions-api-reference#waituntil

mmkal commented 2 weeks ago

It sounds like the above is specific to functions? It's not clear to me if it's supposed to be used in:

I had a look at the implementation and it looks like it's getting context from globalThis, but it null checks both the context's existence and the waitUntil property on the context.

Edited: from adding logging which does roughly the same as the waitUntil export from @vercel/functions, it seems it is defined for middleware, server components and route handlers. When deployed to vercel - it isn't locally, which makes some sense. Not sure about non-vercel deployment environments, or node vs edge, but this is good enough for me! I'm still not sure why the docs only reference functions when it seems to work everywhere, so I might still be missing something.