Konsumsi API elastis di jaringan perusahaan yang tidak dapat diandalkan

 – Beragampengetahuan
18 mins read

Konsumsi API elastis di jaringan perusahaan yang tidak dapat diandalkan – Beragampengetahuan

Jaringan perusahaan sering kali berisik. VPN, WAF, proxy, hotspot seluler, dan kegagalan gateway singkat dapat menyebabkan waktu tunggu habis, kehilangan paket, pembatasan, dan pengaturan ulang koneksi secara tiba-tiba. Merancang klien yang tangguh meminimalkan gesekan checkout/MACD, mencegah duplikasi, dan menjaga UI tetap responsif ketika terjadi ketidakstabilan backend atau jaringan.

Kami memiliki perangkat canggih untuk melakukan panggilan API, namun bagaimana kami membuatnya aman bagi pengguna dan mudah bagi pengembang? Tumpukan mana yang harus kita pilih? Bagaimana cara kami mengurangi duplikasi dan menjaga kode tetap dapat dikelola di seluruh perusahaan? Pertanyaan-pertanyaan ini penting ketika Anda memiliki ratusan titik akhir: beberapa dipicu oleh CTA, beberapa saat memuat halaman, yang lain secara diam-diam mengambil data terlebih dahulu di latar belakang, dan yang lainnya perlu dialirkan. Tidak ada pendekatan yang universal – ada metode yang paling sesuai untuk setiap pekerjaan.

Dalam artikel ini, kami akan membandingkan tiga strategi umum – kueri Ambil, Axios, dan RTK – dan membantu Anda memilih perangkat yang tepat untuk lingkungan Anda. Kami juga akan membagikan contoh nyata yang menghemat waktu dan memecahkan masalah sehari-hari yang dihadapi pengembang.

Contents

Target

  • Elastisitas: Toleransi jaringan yang tidak stabil (WAF, proxy, seluler, VPN).
  • kebenaran: Hindari penulisan duplikat, tangani konkurensi, dan jalankan kontrak.
  • Sederhana: Sentralisasi konfigurasi dan kurangi file boilerplate.
  • Observabilitas: Melacak permintaan, mengukur latensi/kesalahan/percobaan ulang.
  • Keamanan: Melindungi token dan memverifikasi input/output.

Apa yang harus dibahas dalam setiap panggilan API

Kontrak dan ketik

  • Hasilkan tipe dari OpenAPI/Swagger atau validasi saat runtime menggunakan skema.
  • Alat: openapi-typescript, openapi-generator, zod atau valibot.

Otentikasi dan header

  • Melampirkan token/cookie dengan aman; putar/segarkan sesuai kebutuhan.
  • Sertakan header yang relevan (misalnya, X-Request-Id).

waktu habis

  • Batas waktu eksplisit per titik akhir; tetap di bawah batas gateway/WAF.
  • Jaga agar nilai default tetap ketat (misalnya, 8 detik); gunakan waktu tunggu yang lebih singkat untuk titik akhir baca dan waktu tunggu yang sedikit lebih lama untuk jalur tulis yang melibatkan beberapa layanan.
    // api.ts
    import axios from 'axios';
    
    export const api = axios.create(
      baseURL: '/api',
      timeout: 8000, // sensible default; override per request where needed
      withCredentials: true,
      headers:  'Content-Type': 'application/json' 
    );
    
    // Attach a requestId and simple timing metadata
    api.interceptors.request.use((config) => 
      (config as any).metadata =  start: Date.now() ;
      config.headers = 
        ...config.headers,
        'X-Request-Id': crypto.randomUUID()
      ;
      return config;
    );
    
    api.interceptors.response.use(
      (res) => 
        const meta = (res.config as any).metadata;
        if (meta) res.headers['x-client-latency-ms'] = String(Date.now() - meta.start);
        return res;
      ,
      (error) => Promise.reject(error)
    );
    

  • Konfigurasikan batas waktu per permintaan dan berikan pesan kesalahan batas waktu yang ramah.
    // timeouts.ts
    import  api  from './api';
    
    export async function fetchCatalog(signal?: AbortSignal) 
      // Read path: lower timeout
      return api.get('/catalog',  timeout: 5000, signal, timeoutErrorMessage: 'Catalog timed out' );
    
    
    export async function submitOrder(payload: unknown, signal?: AbortSignal) 
      // Write path: a bit higher, but still below gateway/WAF timeouts
      return api.post('/orders', payload,  timeout: 12000, signal, timeoutErrorMessage: 'Order submission timed out' );
    
    

Coba lagi dan mundur

  • Coba lagi idempoten GET/PUT/DELETE atau POST hanya menggunakan kunci idempoten.
  • Mundur dengan hati-hati untuk menghindari kerumunan yang bergemuruh; upaya maksimal dibatasi.
    // retry.ts
    import axios,  AxiosError  from 'axios';
    import  api  from './api';
    
    const MAX_RETRIES = 3;
    const BASE_DELAY_MS = 300;
    
    //could you debounce lib instead 
    function sleep(ms: number)  return new Promise((r) => setTimeout(r, ms)); 
    
    function isIdempotent(method?: string) 
    
    function hasIdempotencyKey(headers?: any)  headers?.['idempotency-key'];
      return Boolean(key);
    
    
    function shouldRetry(error: AxiosError) 
    
    api.interceptors.response.use(undefined, async (error: AxiosError) => );
    

pemecah

  • Mencegah tindakan keras terhadap layanan hilir yang gagal. Setelah N kesalahan berturut-turut, trip dibuka, didinginkan, dan kemudian dibuka setengah untuk mengembalikan probe.
    (Konfigurasi: AxiosRequestConfig): Janji> const sekarang = Tanggal.sekarang(); if (this.state === ‘OPEN’) if (now < this.nextAttemptAt) const err = new axios.AxiosError('sirkuit terbuka', 'ECIRCUITOPEN', config); return Promise.tolak(err); this.state="SETENGAH_OPEN"; coba const res = tunggu ini.klien.permintaan(konfigurasi); ini.onSuccess(); mengembalikan sumber daya; tangkap (kesalahan) this.onFailure(); kesalahan melempar; pribadi onSuccess() this.failures = 0; this.state=”ditutup”; private onFailure() if (this.state === ‘HALF_OPEN’) this.trip(); kembali; ini.kegagalan+= 1; if (this.failures >= this.opts.failureThreshold) this.trip();Perjalanan Pribadi() this.state=”OPEN”; this.nextAttemptAt = Tanggal.sekarang() + this.opts.cooldownMs; // Gunakan impor api dari ‘./api’; untuk mengekspor pemutus sirkuit konstan = new AxiosCircuitBreaker(api, failThreshold: 4, cooldownMs: 10000); // Contoh panggilan // wait Breaker.request( metode: ‘dapatkan’, url: ‘/inventory’ ); ” data-lang = “aplikasi/naskah”>

    // circuitBreaker.ts
    import type  AxiosInstance, AxiosRequestConfig, AxiosResponse  from 'axios';
    import axios from 'axios';
    
    type State="CLOSED" | 'OPEN' | 'HALF_OPEN';
    
    export class AxiosCircuitBreaker 
      private state: State="CLOSED";
      private failures = 0;
      private nextAttemptAt = 0;
    
      constructor(
        private readonly client: AxiosInstance,
        private readonly opts =  failureThreshold: 5, cooldownMs: 15000 
      ) 
    
      async request<T = any>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> 
        const now = Date.now();
    
        if (this.state === 'OPEN') 
          if (now < this.nextAttemptAt) 
            const err = new axios.AxiosError('Circuit open', 'ECIRCUITOPEN', config);
            return Promise.reject(err);
          
          this.state="HALF_OPEN";
        
    
        try 
          const res = await this.client.request<T>(config);
          this.onSuccess();
          return res;
         catch (err) 
          this.onFailure();
          throw err;
        
      
    
      private onSuccess() 
        this.failures = 0;
        this.state="CLOSED";
      
    
      private onFailure() 
        if (this.state === 'HALF_OPEN') 
          this.trip();
          return;
        
        this.failures += 1;
        if (this.failures >= this.opts.failureThreshold) this.trip();
      
    
      private trip() 
        this.state="OPEN";
        this.nextAttemptAt = Date.now() + this.opts.cooldownMs;
      
    
    
    // usage
    import  api  from './api';
    export const breaker = new AxiosCircuitBreaker(api,  failureThreshold: 4, cooldownMs: 10000 );
    
    // Example call
    // await breaker.request( method: 'get', url: '/inventory' );
    

menghapuskan

  • Gunakan AbortController (Axios mendukung AbortSignal standar).
  • Redux Toolkit createAsyncThunk memberi Anda sinyal pembatalan.
s.items = a.payload; s.status=”Sukses”; ) .addCase(fetchProducts.rejected, (s) => s.status=”Gagal”; ); ); ekspor produk default Slice.reducer; “data-lang=”aplikasi/skrip”>

// products.slice.ts
import  createAsyncThunk, createSlice  from '@reduxjs/toolkit';
import  api  from '../api';

export const fetchProducts = createAsyncThunk('products/fetch', async (_,  signal ) => 
  const res = await api.get('/products',  signal, timeout: 6000 );
  return res.data as  id: string; name: string [];
);

const productsSlice = createSlice(
  name: 'products',
  initialState: 'failed' ,
  reducers: ,
  extraReducers: (b) => 
    b.addCase(fetchProducts.pending, (s) =>  s.status="loading"; )
     .addCase(fetchProducts.fulfilled, (s, a) =>  s.items = a.payload; s.status="succeeded"; )
     .addCase(fetchProducts.rejected, (s) =>  s.status="failed"; );
  
);

export default productsSlice.reducer;

// ProductsList.tsx
import  useEffect  from 'react';
import  useAppDispatch, useAppSelector  from './store';
import  fetchProducts  from './products.slice';

export function ProductsList() 
  const dispatch = useAppDispatch();
  const items = useAppSelector((s) => s.products.items);

  useEffect(() => 
    const promise = dispatch(fetchProducts());
    return () => 
      // Abort when the component unmounts or route changes
      promise.abort();
    ;
  , [dispatch]);

  return <ul>items.map((p) => <li key=p.id>p.name</li>)</ul>;

Idempotensi dan konkurensi

  • Jika memungkinkan, pilih PUT/PATCH untuk pembaruan idempoten. Untuk POST yang membuat atau mengubah status server, sertakan header kunci idempotensi untuk memastikan bahwa server menerapkan operasi paling banyak satu kali, bahkan saat percobaan ulang.
  • Gunakan UI optimis untuk segera mencerminkan perubahan yang diharapkan, lalu rekonsiliasi atau kembalikan jika gagal.
  • Untuk pembaruan yang bertentangan, pertimbangkan ETags + If-Match untuk menghindari pembaruan yang hilang.

Pembaruan optimis menggunakan kunci idempoten:

// checkout.slice.ts
import  createSlice, createAsyncThunk, nanoid  from '@reduxjs/toolkit';
import  api  from '../api';

type CartItem =  id: string; qty: number ;
type State =  items: CartItem[]; pendingOps: Record<string,  prev?: CartItem > ;

const initialState: State =  items: [], pendingOps:  ;

export const updateCartItem = createAsyncThunk(
  'checkout/updateCartItem',
  async ( id, qty, idempotencyKey :  id: string; qty: number; idempotencyKey: string ,  signal, rejectWithValue ) => 
    try 
      const res = await api.put(`/cart/items/$id`,  qty , 
        signal,
        timeout: 10000,
        headers:  'Idempotency-Key': idempotencyKey 
      );
      return res.data as CartItem;
     catch (e: any) 
      return rejectWithValue( id, qty, message: e?.message ?? 'update failed' );
    
  
);

const slice = createSlice(
  name: 'checkout',
  initialState,
  reducers: 
    startOptimisticUpdate(s, a:  payload:  id: string; qty: number; opId: string  ) 
      const  id, qty, opId  = a.payload;
      const idx = s.items.findIndex((it) => it.id === id);
      const prev = idx >= 0 ?  ...s.items[idx]  : undefined;
      if (idx >= 0) s.items[idx].qty = qty;
      s.pendingOps[opId] =  prev ;
    ,
    rollback(s, a:  payload:  opId: string  ) 
      const  prev  = s.pendingOps[a.payload.opId] 
  ,
  extraReducers: (b) => 
    b.addCase(updateCartItem.fulfilled, (s, a) => 
      // Confirm final state from server
      const updated = a.payload;
      const idx = s.items.findIndex((it) => it.id === updated.id);
      if (idx >= 0) s.items[idx] = updated;
      // Clean up any matching pending op if you track by id
    )
    .addCase(updateCartItem.rejected, (s, a) => 
      // Rollback is performed from UI where opId is known
    );
  
);

export const  startOptimisticUpdate, rollback  = slice.actions;
export default slice.reducer;

// CartItem.tsx
import  useAppDispatch  from './store';
import  startOptimisticUpdate, updateCartItem, rollback  from './checkout.slice';

export function CartItem( id, qty :  id: string; qty: number ) 
  const dispatch = useAppDispatch();

  const onChangeQty = (nextQty: number) => 
    const opId = crypto.randomUUID();
    const idempotencyKey = opId; // reuse opId for Idempotency-Key

    // 1) optimistic update
    dispatch(startOptimisticUpdate( id, qty: nextQty, opId ));

    // 2) server update with retry/cancellation baked via api config
    const thunk = dispatch(updateCartItem( id, qty: nextQty, idempotencyKey ));

    // 3) rollback on failure
    thunk.unwrap().catch(() => dispatch(rollback( opId )));
  ;

  return (
    <div>
      <span>Qty: qty</span>
      <button onClick=() => onChangeQty(qty + 1)>+</button>
      <button onClick=() => onChangeQty(qty - 1)>-</button>
    </div>
  );

Catatan Pembayaran/MACD:

  • Gunakan kunci idempoten yang sama saat mencoba kembali permintaan POST/PUT untuk mencegah duplikat baris pesanan atau duplikat perubahan MACD.
  • Untuk MACD, pertimbangkan untuk menyatakan setiap perubahan sebagai sumber daya deterministik (PUT /services/id/config) sehingga percobaan ulang tetap aman.
  • Jika server mendukung ETags, tambahkan header If-Match untuk memastikan pembaruan serentak tidak ditimpa.

Penanganan kesalahan

  • Normalisasi kesalahan ke dalam satu bentuk UI; memetakan kode status yang diketahui ke pesan ramah.
    • bentuk yang salah – Bidang konsisten yang dapat diandalkan oleh UI (pesan, status, dapat dicoba ulang, requestId, detail).
    • pemetaan deterministik – Kode status yang diketahui dan kesalahan transmisi menjadi pesan yang jelas dan dapat dibaca manusia.
    • pemisahan kekhawatiran – Pertahankan kesalahan tingkat rendah dalam perjalanan; normalkan pada batas (thunks/RTK Query baseQuery) sehingga percobaan ulang/pemutus sirkuit masih berfungsi.

Contoh TypeScript: normalizer dan penggunaan (kueri Axios dan RTK):

// error.ts
import type  AxiosError  from 'axios';

export type AppError = 
  code: string;
  status?: number;
  message: string;
  requestId?: string;
  retryable: boolean;
  details?: unknown;
;

const FRIENDLY: Record<number,  code: string; message: string; retryable: boolean > = 
  400:  code: 'BAD_REQUEST',       message: 'Request is invalid. Please check inputs.',         retryable: false ,
  401:  code: 'UNAUTHENTICATED',   message: 'You’re signed out. Please sign in and try again.', retryable: false ,
  403:  code: 'FORBIDDEN',         message: 'You don’t have permission to do this.',            retryable: false ,
  404:  code: 'NOT_FOUND',         message: 'The resource was not found.',                      retryable: false ,
  409:  code: 'CONFLICT',          message: 'Your changes conflict with another update.',       retryable: true  ,
  412:  code: 'PRECONDITION',      message: 'Version mismatch. Refresh and try again.',         retryable: true  ,
  422:  code: 'VALIDATION',        message: 'Some fields need attention.',                      retryable: false ,
  425:  code: 'TOO_EARLY',         message: 'Service not ready. Please try again shortly.',     retryable: true  ,
  429:  code: 'RATE_LIMITED',      message: 'Too many requests. Please wait and retry.',        retryable: true  ,
  500:  code: 'SERVER_ERROR',      message: 'We hit a snag. Please try again.',                 retryable: true  ,
  502:  code: 'BAD_GATEWAY',       message: 'Upstream gateway error. Try again.',               retryable: true  ,
  503:  code: 'UNAVAILABLE',       message: 'Service is temporarily unavailable.',              retryable: true  ,
  504:  code: 'GATEWAY_TIMEOUT',   message: 'Service timed out. Please try again.',             retryable: true  
;

export function normalizeAxiosError(e: unknown): AppError 

function defaultFor(status?: number) 
  if (!status) return  code: 'UNKNOWN', message: 'Unexpected error. Please try again.', retryable: true ;
  if (status >= 500) return  code: 'SERVER_ERROR', message: 'We hit a snag. Please try again.', retryable: true ;
  return  code: 'CLIENT_ERROR', message: 'Something went wrong with the request.', retryable: false ;

Digunakan dengan Axios thunk (pertahankan percobaan ulang/pemutus sirkuit dalam perjalanan; normalkan pada batas):

// orders.thunk.ts
import  createAsyncThunk  from '@reduxjs/toolkit';
import  api  from './api';
import  normalizeAxiosError, type AppError  from './error';

export const fetchOrder = createAsyncThunk<any, string,  rejectValue: AppError >(
  'orders/fetch',
  async (id,  signal, rejectWithValue ) => 
    try 
      const res = await api.get(`/orders/$id`,  signal, timeout: 8000 );
      return res.data;
     catch (err) 
      return rejectWithValue(normalizeAxiosError(err));
    
  
);

Digunakan dengan baseQuery kueri RTK (semua kesalahan menjadi AppError):

// rtkAxiosBaseQuery.ts
import type  BaseQueryFn  from '@reduxjs/toolkit/query';
import type  AxiosRequestConfig  from 'axios';
import  api  from './api';
import  normalizeAxiosError, type AppError  from './error';

export const axiosBaseQuery = (): BaseQueryFn<AxiosRequestConfig, unknown, AppError> =>
  async (config) => 
    try 
      const res = await api.request(config);
      return  data: res.data ;
     catch (e) 
      return  error: normalizeAxiosError(e) ;
    
  ;

Contoh penggunaan UI sederhana:

// ErrorBanner.tsx
import type  AppError  from './error';

export function ErrorBanner( error :  error: AppError ) 
  return (
    <div role="alert">
      <strong>error.message</strong>
      error.requestId && <small> · Ref: error.requestId</small>
      error.retryable && <button onClick=() => window.location.reload()>Try again</button>
    </div>
  );

Observabilitas

  • Mencatat requestId, latensi, jumlah percobaan ulang, dan status pemutus sirkuit; terintegrasi dengan APM Anda.

Kinerja dan cache

  • Hapus duplikat permintaan yang sedang berlangsung
  • Data baca cache (dengan TTL)
  • Tidak valid dengan tag (kueri RTK)

Hapus duplikat permintaan dalam penerbangan (Axios). Hindari memicu GET duplikat dari beberapa komponen secara bersamaan dengan menggunakan kembali Promise yang sama.

// inflight.ts
import  api  from './api';

const inflight = new Map<string, Promise<any>>();

function stable(params: Record<string, any> = ) 
  return JSON.stringify(Object.keys(params).sort().reduce((a, k) => (a[k] = params[k], a),  as any));


export function getWithDedupe<T>(url: string, params: Record<string, any> = , timeout = 6000) 
  const key = `GET $url?$stable(params)`;
  const existing = inflight.get(key);
  if (existing) return existing as Promise< data: T >;

  const p = api.get<T>(url,  params, timeout )
    .finally(() => inflight.delete(key));
  inflight.set(key, p as Promise<any>);
  return p;


// usage
// const  data  = await getWithDedupe<Product[]>('/products',  q: 'router' );

Cache baca sederhana dengan TTL (Axios). Simpan respons GET yang berhasil dalam cache selama jangka waktu tertentu untuk mengurangi beban jaringan.

// ttlCache.ts
import  api  from './api';

type Entry<T> =  expires: number; data: T ;
const cache = new Map<string, Entry<any>>();

function now()  return Date.now(); 
function key(url: string, params?: Record<string, any>) 
  return `GET $url:$JSON.stringify(params ?? )`;


export async function getCached<T>(url: string, params?: Record<string, any>, ttlMs = 30_000) 
  const k = key(url, params);
  const hit = cache.get(k);
  if (hit && hit.expires > now()) 
    return  data: hit.data as T, fromCache: true as const ;
  
  const res = await api.get<T>(url,  params, timeout: 6000 );
  cache.set(k,  data: res.data, expires: now() + ttlMs );
  return  data: res.data, fromCache: false as const ;


// usage
// const res = await getCached<Product[]>('/products',  q: '5g' , 60000);

Kueri RTK: caching, deduplikasi, dan pembatalan validasi berbasis tag. RTK menanyakan respons cache, menghapus duplikat data yang diminta saat transit, dan memungkinkan Anda membatalkan validasi data tertentu melalui tag.

// services/products.api.ts
import  createApi  from '@reduxjs/toolkit/query/react';
import  axiosBaseQuery  from './rtkAxiosBaseQuery'; // wraps your Axios instance

type Product =  id: string; name: string; price: number ;

export const productsApi = createApi({
  reducerPath: 'productsApi',
  baseQuery: axiosBaseQuery(),
  tagTypes: ['Product'],
  keepUnusedDataFor: 60, // seconds
  endpoints: (build) => (
    getProducts: build.query<Product[], void>(
      query: () => ( url: '/products', method: 'GET', timeout: 5000 ),
      providesTags: (result) =>
        result
          ? [
              ...result.map((p) => ( type: 'Product' as const, id: p.id )),
               type: 'Product' as const, id: 'LIST' 
            ]
          : [ type: 'Product', id: 'LIST' ]
    ),
    updateProduct: build.mutation<Product, Partial<Product> & Pick<Product, 'id'>>(
      query: ( id, ...patch ) => (
        url: `/products/$id`,
        method: 'PATCH',
        data: patch,
        headers:  'Idempotency-Key': crypto.randomUUID() 
      ),
      // Invalidate the specific product and the list
      invalidatesTags: (result, error,  id ) => [ type: 'Product', id ,  type: 'Product', id: 'LIST' ]
    ),
    createProduct: build.mutation<Product, Omit<Product, 'id'>>(
      query: (body) => ( url: '/products', method: 'POST', data: body ),
      invalidatesTags: [ type: 'Product', id: 'LIST' ]
    )
  )
});

export const  useGetProductsQuery, useUpdateProductMutation, useCreateProductMutation  = productsApi;

// usage in a component
// const  data, isFetching  = useGetProductsQuery();
// const [updateProduct] = useUpdateProductMutation();

Keamanan dan Kepatuhan

  • Tidak ada PII yang dicatat.
  • Edit bidang sensitif.
  • Mematuhi CSP/CORS.
  • Hanya token dalam memori yang dilindungi.

Daftar Periksa Cepat Jaringan Perusahaan

  • Batas waktu ditentukan per permintaan dan selalu di bawah batas gateway/WAF.
  • Percobaan ulang terbatas, kemunduran eksponensial, dan jitter.
  • Aktifkan pemutus sirkuit per domain layanan.
  • Semua permintaan dapat dibatalkan; navigasi akan membatalkan panggilan dalam penerbangan.
  • UI optimis dengan rollback dan kunci idempotensi sisi server.
  • Observabilitas: Melacak jumlah percobaan ulang, status pemutus sirkuit, dan tingkat batas waktu.

Contoh sederhana ujung ke ujung di satu tempat:

// endToEnd.ts
import  breaker  from './circuitBreaker';

export async function safeGet<T>(url: string, signal?: AbortSignal, timeout = 6000) 
  // GET with timeout, retries (via interceptor), and circuit breaker
  return breaker.request<T>( method: 'GET', url, signal, timeout ).then((r) => r.data);


export async function safeIdempotentPost<T>(url: string, body: unknown, signal?: AbortSignal, timeout = 10000) 
  const idempotencyKey = crypto.randomUUID();
  return breaker
    .request<T>( method: 'POST', url, data: body, signal, timeout, headers:  'Idempotency-Key': idempotencyKey  )
    .then((r) => r.data);

Panduan Keputusan (Perbandingan Cepat)

Variasi: Ambil vs. Axios vs. Kueri RTK (cocok untuk masing-masing)

bawa itu (nasional)

  • keuntungan: Dukungan streaming bawaan, berbasis standar, Permintaan/AbortController.
  • kekurangan: Tidak ada pencegat, batas waktu manual (melalui AbortController), penguraian JSON/kesalahan manual, tidak ada percobaan ulang bawaan.
  • Saat menggunakan: Anda menginginkan ketergantungan minimal atau memerlukan aliran; bersiap untuk membuat pembungkusnya.
  • dokter:

aksio (perpustakaan)

  • Kelebihan: Pencegat, API bersih, batas waktu per permintaan, JSON default, objek kesalahan bagus, dan kemajuan unggah/unduh.
  • Kekurangan: Tidak ada caching/deduplikasi bawaan, Anda mengelola sendiri percobaan ulang dan pembatalan.
  • Kapan menggunakan: Anda memerlukan kontrol terpusat (header, autentikasi, pelacakan) dan perilaku perusahaan (percobaan ulang, pemutus sirkuit).
  • dokumen:

permintaan RTK (Permintaan perangkat Redux)

  • Kelebihan: Caching/deduplikasi, polling, perolehan kembali/koneksi ulang fokus, pembaruan optimis, pembatalan otomatis, build hooks, integrasi dengan Redux DevTools.
  • Kekurangan: Kurva pembelajaran untuk tag/penonaktifan; Anda tetap akan memilih pengambilan atau aksio sebagai transportasi yang mendasarinya.
  • Kapan menggunakannya: Anda ingin menstandardisasi pengambilan data dengan caching kelas satu dan meminta manajemen siklus hidup.
  • dokumen:

Panduan pengambilan keputusan

memilih aksio Jika Anda membutuhkan:

  • Anda memerlukan kontrol menyeluruh atas pencegat, pemutus sirkuit khusus, proksi perusahaan/nuansa WAF, dan header autentikasi non-standar.
  • Anda sudah memiliki middleware, logging, dan observabilitas penting yang dibangun di sekitar Axios.
  • Anda lebih memilih kepemilikan eksplisit atas logika cache, deduplikasi, dan pembatalan.

memilih permintaan RTK (Didukung oleh Axios) Jika Anda membutuhkan:

  • Anda memerlukan caching bawaan, deduplikasi, polling, pengambilan ulang pada fokus/sambungan ulang, dan meminta manajemen siklus hidup.
  • Anda lebih suka menggunakan hook yang dihasilkan dan boilerplate minimal untuk mendapatkan data.
  • Anda menginginkan pembaruan dan pembatalan optimis kelas satu melalui onQueryStarted dan patchQueryData.
  • Anda dapat menstandardisasi baseQuery (pengambilan atau aksio) dan tag untuk pembatalan cache.

memilih Akuisisi normal jika Anda:

  • Tidak menginginkan ketergantungan dan bersedia membuat wrapper untuk batas waktu, percobaan ulang, dan penanganan kesalahan.

kompromi yang baik: Menyimpan aksio sebagai transportasi dan penggunaan permintaan RTKBaseQuery yang kompatibel dengan Axios, sehingga Anda dapat mempertahankan logika pencegat, batas waktu, percobaan ulang, dan pemutus sirkuit sambil mendapatkan cache dan siklus hidup kueri RTK.

Gunakan Axios untuk kueri RTK:

// rtkAxiosBaseQuery.ts
import type  BaseQueryFn  from '@reduxjs/toolkit/query';
import type  AxiosRequestConfig, AxiosError  from 'axios';
import  api  from './api'; // your axios instance with interceptors

export const axiosBaseQuery =
  (): BaseQueryFn<AxiosRequestConfig, unknown, unknown> =>
  async (config) => 
    try 
      const result = await api.request(config);
      return  data: result.data ;
     catch (axiosError) 
      const err = axiosError as AxiosError;
      return 
        error: 
      ;
    
  ;

fitur Dapatkan (lokal) Aksio (perpustakaan) permintaan RTK
(Permintaan perangkat Redux)
Dibangun ke dalam platform
Respons streaming (browser)
Pencegat ◐ (melalui baseQuery/transportasi)
Batas waktu per permintaan ◐(melalui transportasi)
Batalkan/batalkan permintaan ✓ (batalkan pengontrol) ✓ (batalkan sinyal) ✓ (pembatalan otomatis)
Percobaan ulang bawaan ◐ (Coba lagi pengemasan)
Caching dan deduplikasi
Dapatkan kembali fokus/sambungkan kembali
pemungutan suara
pembaruan optimis
Kait React yang dihasilkan
Integrasi Redux DevTools
Kemajuan unggah/unduh (browser)
Objek kesalahan kaya ◐ (bentuk standar)
Penguraian JSON otomatis —(res.json)
Batalkan cache melalui tag
Minta deduplikasi
Digunakan dengan header autentikasi khusus ✓ (panduan) ✓ (melalui baseQuery)

Dokumen penting:

rencana pengembangan website



metode pengembangan website

jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website

#Konsumsi #API #elastis #jaringan #perusahaan #yang #tidak #dapat #diandalkan

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *