Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

after() API - Wykonywanie kodu po odpowiedzi

W infrastrukturze Metropolii Quantum 2150, gdzie każda operacja musi być zoptymalizowana, poznasz API

after()
- funkcję pozwalającą wykonywać kod po wysłaniu odpowiedzi do użytkownika. To idealne rozwiązanie dla zadań takich jak logowanie, analityka czy cleanup.

Problem: Blokujące operacje poboczne

Wyobraź sobie typowy scenariusz - użytkownik odwiedza stronę produktu, a ty chcesz:

  1. Zwrócić dane produktu (kluczowe)
  2. Zalogować wizytę (poboczne)
  3. Zaktualizować statystyki (poboczne)
  4. Wysłać event do analytics (poboczne)

Bez

after()
, wszystkie te operacje blokują odpowiedź:

1// ❌ Złe podejście - wszystko blokuje odpowiedź
2export async function GET(request: Request) {
3  const product = await getProduct(id);
4
5  // Te operacje opóźniają odpowiedź!
6  await logVisit(id);
7  await updateStats(id);
8  await sendAnalytics('product_view', { id });
9
10  return Response.json(product);
11}

Rozwiązanie: after() API

after()
pozwala zaplanować kod do wykonania PO wysłaniu odpowiedzi:

1import { after } from 'next/server';
2
3export async function GET(request: Request) {
4  const product = await getProduct(id);
5
6  // Zaplanuj wykonanie po odpowiedzi
7  after(async () => {
8    await logVisit(id);
9    await updateStats(id);
10    await sendAnalytics('product_view', { id });
11  });
12
13  // Odpowiedź wysyłana natychmiast!
14  return Response.json(product);
15}

Włączenie after() API

after()
wymaga włączenia flagi eksperymentalnej:

1// next.config.js
2module.exports = {
3  experimental: {
4    after: true,
5  },
6};

Użycie w różnych kontekstach

W Route Handlers

1// app/api/orders/route.ts
2import { after } from 'next/server';
3import { sendEmail, updateInventory, notifyWarehouse } from '@/lib/services';
4
5export async function POST(request: Request) {
6  const orderData = await request.json();
7
8  // Kluczowa operacja - tworzenie zamówienia
9  const order = await createOrder(orderData);
10
11  // Operacje poboczne - wykonane po odpowiedzi
12  after(async () => {
13    // Email potwierdzający
14    await sendEmail({
15      to: orderData.email,
16      subject: 'Potwierdzenie zamówienia',
17      template: 'order-confirmation',
18      data: order,
19    });
20
21    // Aktualizacja stanów magazynowych
22    await updateInventory(order.items);
23
24    // Powiadomienie magazynu
25    await notifyWarehouse(order);
26
27    // Logowanie do systemu audytu
28    await auditLog('order_created', { orderId: order.id });
29  });
30
31  // Odpowiedź natychmiastowa
32  return Response.json({
33    success: true,
34    orderId: order.id
35  });
36}

W Server Components

1// app/products/[id]/page.tsx
2import { after } from 'next/server';
3import { trackPageView } from '@/lib/analytics';
4
5export default async function ProductPage({ params }: { params: Promise<{ id: string }> }) {
6  const product = await getProduct((await params).id);
7
8  // Tracking po renderowaniu strony
9  after(async () => {
10    await trackPageView({
11      page: 'product',
12      productId: (await params).id,
13      productName: product.name,
14      category: product.category,
15    });
16  });
17
18  return (
19    <div className="product-page">
20      <h1>{product.name}</h1>
21      <p>{product.description}</p>
22      <span className="price">{product.price}</span>
23    </div>
24  );
25}

W Server Actions

1// app/actions/checkout.ts
2'use server';
3
4import { after } from 'next/server';
5import { revalidatePath } from 'next/cache';
6
7export async function completeCheckout(formData: FormData) {
8  const cartId = formData.get('cartId') as string;
9
10  // Kluczowa operacja
11  const order = await processPayment(cartId);
12
13  if (!order.success) {
14    return { error: 'Płatność nie powiodła się' };
15  }
16
17  // Rewalidacja ścieżek
18  revalidatePath('/cart');
19  revalidatePath('/orders');
20
21  // Operacje poboczne po odpowiedzi
22  after(async () => {
23    // Czyszczenie koszyka w tle
24    await clearCart(cartId);
25
26    // Generowanie faktury PDF
27    await generateInvoice(order.id);
28
29    // Integracje zewnętrzne
30    await syncWithERP(order);
31    await notifyShipping(order);
32
33    // Aktualizacja programu lojalnościowego
34    await updateLoyaltyPoints(order.userId, order.total);
35  });
36
37  return { success: true, orderId: order.id };
38}

Wiele wywołań after()

Możesz użyć

after()
wielokrotnie - wszystkie callbacki zostaną wykonane:

1import { after } from 'next/server';
2
3export async function POST(request: Request) {
4  const data = await request.json();
5  const result = await processData(data);
6
7  // Logowanie
8  after(async () => {
9    await logger.info('Data processed', { id: result.id });
10  });
11
12  // Analytics
13  after(async () => {
14    await analytics.track('data_processed', {
15      processingTime: result.duration,
16      dataSize: data.length,
17    });
18  });
19
20  // Cleanup
21  after(async () => {
22    await cleanupTempFiles(result.tempPath);
23  });
24
25  return Response.json(result);
26}

Obsługa błędów w after()

Błędy w

after()
nie wpływają na odpowiedź, ale powinny być obsługiwane:

1import { after } from 'next/server';
2
3export async function GET(request: Request) {
4  const data = await fetchData();
5
6  after(async () => {
7    try {
8      await riskyOperation();
9    } catch (error) {
10      // Loguj błąd, ale nie przerywaj
11      console.error('After callback failed:', error);
12      await errorReporting.capture(error);
13    }
14  });
15
16  return Response.json(data);
17}

Praktyczny przykład - System notyfikacji

1// app/api/posts/[id]/like/route.ts
2import { after } from 'next/server';
3import { getSession } from '@/lib/auth';
4
5export async function POST(
6  request: Request,
7  { params }: { params: Promise<{ id: string }> }
8) {
9  const session = await getSession();
10  if (!session) {
11    return Response.json({ error: 'Unauthorized' }, { status: 401 });
12  }
13
14  // Kluczowa operacja - dodanie like'a
15  const like = await addLike((await params).id, session.userId);
16
17  // Wszystkie powiadomienia i side effects po odpowiedzi
18  after(async () => {
19    const post = await getPost((await params).id);
20
21    // Powiadomienie autora posta
22    if (post.authorId !== session.userId) {
23      await createNotification({
24        userId: post.authorId,
25        type: 'like',
26        message: `${session.user.name} polubił Twój post`,
27        link: `/posts/${(await params).id}`,
28      });
29
30      // Push notification
31      await sendPushNotification(post.authorId, {
32        title: 'Nowy like!',
33        body: `${session.user.name} polubił Twój post`,
34      });
35    }
36
37    // Aktualizacja statystyk
38    await incrementPostStats((await params).id, 'likes');
39
40    // Aktualizacja feed algorytmu
41    await updateFeedRanking((await params).id, 'engagement');
42  });
43
44  return Response.json({ liked: true, likeCount: like.count });
45}

Kiedy używać after()?

✅ Idealne przypadki użycia:

  • Logowanie i audyt - zapisywanie działań użytkowników
  • Analytics - śledzenie eventów i metryk
  • Powiadomienia - wysyłanie emaili, push notifications
  • Cleanup - czyszczenie plików tymczasowych
  • Synchronizacja - aktualizacja zewnętrznych systemów
  • Generowanie raportów - tworzenie plików w tle

❌ Nie używaj dla:

  • Walidacji - musi być przed odpowiedzią
  • Autoryzacji - musi być przed odpowiedzią
  • Danych potrzebnych w odpowiedzi - oczywiste!
  • Operacji wymagających potwierdzenia - użytkownik nie zobaczy wyniku

Podsumowanie

API

after()
w Next.js to potężne narzędzie optymalizacji:

  • Szybsze odpowiedzi - operacje poboczne nie blokują użytkownika
  • Lepsza UX - użytkownik widzi wynik natychmiast
  • Czystszy kod - wyraźna separacja operacji kluczowych i pobocznych
  • Niezawodność - błędy w after() nie psują odpowiedzi

W Metropolii Quantum 2150, gdzie każda milisekunda ma znaczenie,

after()
pozwala twoim aplikacjom działać z prędkością światła, podczas gdy operacje poboczne wykonują się spokojnie w tle!

Vai a CodeWorlds