Slovenščina

Obvladajte varno tipizirane klice API v TypeScript za robustne, vzdržljive in sproščene spletne aplikacije. Spoznajte najboljše prakse in napredne tehnike.

Varno tipizirani klici API z uporabo TypeScript: Celovit vodič

V modernem spletnem razvoju je interakcija z API-ji temeljna naloga. TypeScript s svojim močnim tipiziranim sistemom ponuja veliko prednost pri zagotavljanju zanesljivosti in vzdržljivosti vaših aplikacij, saj omogoča varno tipizirane klice API. Ta vodič bo raziskal, kako izkoristiti funkcije TypeScripta za izgradnjo robustnih in sproščenih interakcij API, ki zajemajo najboljše prakse, napredne tehnike in primere iz resničnega sveta.

Zakaj je varnost tipov pomembna za klice API

Pri delu z API-ji se v bistvu ukvarjate s podatki, ki prihajajo iz zunanjega vira. Ti podatki morda niso vedno v obliki, ki jo pričakujete, kar vodi do napak med izvajanjem in nepričakovanega vedenja. Varnost tipov zagotavlja ključno raven zaščite s preverjanjem, ali so podatki, ki jih prejmete, skladni z vnaprej določeno strukturo, kar omogoča zgodnje odkrivanje morebitnih težav v procesu razvoja.

Nastavitev vašega projekta TypeScript

Preden se potopite v klice API, se prepričajte, da imate nastavljen projekt TypeScript. Če začenjate iz nič, lahko inicializirate nov projekt z:

npm init -y
npm install typescript --save-dev
tsc --init

To bo ustvarilo datoteko `tsconfig.json` s privzetimi možnostmi prevajalnika TypeScript. Te možnosti lahko prilagodite svojim potrebam projekta. Na primer, morda boste želeli omogočiti strogi način za strožje preverjanje tipov:

// tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Določanje tipov za odzive API

Prvi korak pri doseganju varnih tipiziranih klicev API je določiti tipe TypeScript, ki predstavljajo strukturo podatkov, ki jih pričakujete prejeti od API-ja. To se običajno naredi z uporabo deklaracij `interface` ali `type`.

Uporaba vmesnikov

Vmesniki so močan način za določanje oblike predmeta. Na primer, če pridobivate seznam uporabnikov iz API-ja, lahko definirate vmesnik, kot je ta:

interface User {
  id: number;
  name: string;
  email: string;
  address?: string; // Izbirna lastnost
  phone?: string; // Izbirna lastnost
  website?: string; // Izbirna lastnost
  company?: {
    name: string;
    catchPhrase: string;
    bs: string;
  };
}

`?` za imenom lastnosti označuje, da je lastnost izbirna. To je uporabno za obravnavo odzivov API, kjer nekatere polja morda manjkajo.

Uporaba tipov

Tipi so podobni vmesnikom, vendar ponujajo večjo prilagodljivost, vključno z možnostjo določanja sindikalnih in presečnih tipov. Isti rezultat kot vmesnik zgoraj lahko dosežete z uporabo tipa:

type User = {
  id: number;
  name: string;
  email: string;
  address?: string; // Izbirna lastnost
  phone?: string; // Izbirna lastnost
  website?: string; // Izbirna lastnost
  company?: {
    name: string;
    catchPhrase: string;
    bs: string;
  };
};

Za preproste predmetne strukture so vmesniki in tipi pogosto zamenljivi. Vendar pa tipi postanejo močnejši pri obravnavanju bolj zapletenih scenarijev.

Izvajanje klicev API z Axios

Axios je priljubljen HTTP odjemalec za izvajanje zahtev API v JavaScript in TypeScript. Zagotavlja čisto in intuitivno API, ki olajša obravnavo različnih HTTP metod, glav zahtev in podatkov odziva.

Namestitev Axios

npm install axios

Izvajanje tipiziranega klica API

Za izvajanje varno tipiziranega klica API z Axios lahko uporabite metodo `axios.get` in določite pričakovani tip odziva z uporabo generičnih tipov:

import axios from 'axios';

async function fetchUsers(): Promise {
  try {
    const response = await axios.get('https://jsonplaceholder.typicode.com/users');
    return response.data;
  } catch (error) {
    console.error('Napaka pri pridobivanju uporabnikov:', error);
    throw error;
  }
}

fetchUsers().then(users => {
  users.forEach(user => {
    console.log(user.name);
  });
});

V tem primeru `axios.get('...')` pove TypeScriptu, da se pričakuje, da bodo podatki odziva niz objektov `User`. To TypeScriptu omogoča, da zagotovi preverjanje tipov in samodejno dokončevanje pri delu s podatki odziva.

Obravnavanje različnih metod HTTP

Axios podpira različne metode HTTP, vključno z `GET`, `POST`, `PUT`, `DELETE` in `PATCH`. Uporabite lahko ustrezne metode za izvajanje različnih vrst zahtev API. Na primer, za ustvarjanje novega uporabnika lahko uporabite metodo `axios.post`:

async function createUser(user: Omit): Promise {
  try {
    const response = await axios.post('https://jsonplaceholder.typicode.com/users', user);
    return response.data;
  } catch (error) {
    console.error('Napaka pri ustvarjanju uporabnika:', error);
    throw error;
  }
}

const newUser = {
  name: 'John Doe',
  email: 'john.doe@example.com',
  address: '123 Main St',
  phone: '555-1234',
  website: 'example.com',
  company: {
    name: 'Example Corp',
    catchPhrase: 'Leading the way',
    bs: 'Innovative solutions'
  }
};

createUser(newUser).then(user => {
  console.log('Ustvarjen uporabnik:', user);
});

V tem primeru `Omit` ustvari tip, ki je enak `User`, vendar brez lastnosti `id`. To je uporabno, ker `id` običajno ustvari strežnik pri ustvarjanju novega uporabnika.

Uporaba Fetch API

Fetch API je vgrajen JavaScript API za izvajanje HTTP zahtev. Čeprav je bolj osnoven kot Axios, ga je mogoče uporabiti tudi s TypeScript za doseganje varnih tipiziranih klicev API. Morda ga boste raje uporabili, da se izognete dodajanju odvisnosti, če ustreza vašim potrebam.

Izvajanje tipiziranega klica API s Fetch

Za izvajanje varno tipiziranega klica API s Fetch lahko uporabite funkcijo `fetch` in nato razčlenite odziv kot JSON, pri čemer določite pričakovani tip odziva:

async function fetchUsers(): Promise {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    if (!response.ok) {
      throw new Error(`Napaka HTTP! status: ${response.status}`);
    }
    const data: User[] = await response.json();
    return data;
  } catch (error) {
    console.error('Napaka pri pridobivanju uporabnikov:', error);
    throw error;
  }
}

fetchUsers().then(users => {
  users.forEach(user => {
    console.log(user.name);
  });
});

V tem primeru `const data: User[] = await response.json();` pove TypeScriptu, da je treba podatke odziva obravnavati kot niz objektov `User`. To TypeScriptu omogoča izvajanje preverjanja tipov in samodejnega dokončevanja.

Obravnavanje različnih metod HTTP s Fetch

Za izvajanje različnih vrst zahtev API s Fetch lahko uporabite funkcijo `fetch` z različnimi možnostmi, kot sta `method` in `body`. Na primer, za ustvarjanje novega uporabnika lahko uporabite naslednjo kodo:

async function createUser(user: Omit): Promise {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(user)
    });
    if (!response.ok) {
      throw new Error(`Napaka HTTP! status: ${response.status}`);
    }
    const data: User = await response.json();
    return data;
  } catch (error) {
    console.error('Napaka pri ustvarjanju uporabnika:', error);
    throw error;
  }
}

const newUser = {
  name: 'John Doe',
  email: 'john.doe@example.com',
  address: '123 Main St',
  phone: '555-1234',
  website: 'example.com',
  company: {
    name: 'Example Corp',
    catchPhrase: 'Leading the way',
    bs: 'Innovative solutions'
  }
};

createUser(newUser).then(user => {
  console.log('Ustvarjen uporabnik:', user);
});

Obravnavanje napak API

Obravnavanje napak je kritičen vidik klicev API. API-ji lahko odpovejo zaradi številnih razlogov, vključno s težavami s povezljivostjo omrežja, napakami strežnika in neveljavnimi zahtevami. Bistveno je, da te napake obravnavate na eleganten način, da preprečite zrušitev vaše aplikacije ali prikaz nepričakovanega vedenja.

Uporaba blokov Try-Catch

Najpogostejši način za obravnavanje napak v asinhroni kodi je uporaba blokov try-catch. To vam omogoča, da ujamete vse izjeme, ki so vržene med klicem API, in jih ustrezno obravnavate.

async function fetchUsers(): Promise {
  try {
    const response = await axios.get('https://jsonplaceholder.typicode.com/users');
    return response.data;
  } catch (error) {
    console.error('Napaka pri pridobivanju uporabnikov:', error);
    // Obravnavajte napako, npr. prikažite sporočilo o napaki uporabniku
    throw error; // Ponovno vrnite napako, da jo lahko obravnava tudi klicna koda
  }
}

Obravnavanje specifičnih kod napak

API-ji pogosto vračajo specifične kode napak, ki označujejo vrsto napake, ki se je pojavila. Te kode napak lahko uporabite za zagotavljanje natančnejšega obravnavanja napak. Na primer, morda boste želeli prikazati drugačno sporočilo o napaki za napako 404 Not Found kot za napako 500 Internal Server Error.

async function fetchUser(id: number): Promise {
  try {
    const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`);
    return response.data;
  } catch (error: any) {
    if (error.response?.status === 404) {
      console.log(`Uporabnik z ID ${id} ni bil najden.`);
      return null; // Ali vrnite napako po meri
    } else {
      console.error('Napaka pri pridobivanju uporabnika:', error);
      throw error;
    }
  }
}

fetchUser(123).then(user => {
  if (user) {
    console.log('Uporabnik:', user);
  } else {
    console.log('Uporabnik ni bil najden.');
  }
});

Ustvarjanje tipov napak po meri

Za bolj zapletene scenarije obravnavanja napak lahko ustvarite tipe napak po meri za predstavitev različnih vrst napak API. To vam omogoča zagotavljanje bolj strukturiranih informacij o napakah in učinkovitejše obravnavanje napak.

class ApiError extends Error {
  constructor(public statusCode: number, message: string) {
    super(message);
    this.name = 'ApiError';
  }
}

async function fetchUser(id: number): Promise {
  try {
    const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`);
    return response.data;
  } catch (error: any) {
    if (error.response?.status === 404) {
      throw new ApiError(404, `Uporabnik z ID ${id} ni bil najden.`);
    } else {
      console.error('Napaka pri pridobivanju uporabnika:', error);
      throw new ApiError(500, 'Internal Server Error'); //Ali katera koli druga primerna koda stanja
    }
  }
}

fetchUser(123).catch(error => {
  if (error instanceof ApiError) {
    console.error(`API Napaka: ${error.statusCode} - ${error.message}`);
  } else {
    console.error('Pojavila se je nepričakovana napaka:', error);
  }
});

Validacija podatkov

Tudi s sistemom tipov TypeScript je ključnega pomena, da validirate podatke, ki jih prejmete od API-jev, med izvajanjem. API-ji lahko spremenijo svojo strukturo odziva brez opozorila, vaši tipi TypeScript pa morda niso vedno popolnoma sinhronizirani z dejanskim odzivom API-ja.

Uporaba Zod za validacijo med izvajanjem

Zod je priljubljena knjižnica TypeScript za validacijo podatkov med izvajanjem. Omogoča vam definiranje shem, ki opisujejo pričakovano strukturo vaših podatkov, in nato validiranje podatkov glede na te sheme med izvajanjem.

Namestitev Zod

npm install zod

Validacija odzivov API z Zod

Za validacijo odzivov API z Zod lahko definirate shemo Zod, ki ustreza vašemu tipu TypeScript, in nato uporabite metodo `parse` za validacijo podatkov.

import { z } from 'zod';

const userSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
  address: z.string().optional(),
  phone: z.string().optional(),
  website: z.string().optional(),
  company: z.object({
    name: z.string(),
    catchPhrase: z.string(),
    bs: z.string(),
  }).optional(),
});

type User = z.infer;

async function fetchUsers(): Promise {
  try {
    const response = await axios.get('https://jsonplaceholder.typicode.com/users');
    const data = z.array(userSchema).parse(response.data);
    return data;
  } catch (error) {
    console.error('Napaka pri pridobivanju uporabnikov:', error);
    throw error;
  }
}

V tem primeru `z.array(userSchema).parse(response.data)` validira, da so podatki odziva niz objektov, ki so skladni z `userSchema`. Če podatki niso skladni s shemo, bo Zod vrnil napako, ki jo lahko nato ustrezno obravnavate.

Napredne tehnike

Uporaba generikov za funkcije API za večkratno uporabo

Generiki vam omogočajo pisanje funkcij API za večkratno uporabo, ki lahko obravnavajo različne tipe podatkov. Na primer, lahko ustvarite generično funkcijo `fetchData`, ki lahko pridobi podatke iz katere koli končne točke API in jih vrne s pravilnim tipom.

async function fetchData(url: string): Promise {
  try {
    const response = await axios.get(url);
    return response.data;
  } catch (error) {
    console.error(`Napaka pri pridobivanju podatkov iz ${url}:`, error);
    throw error;
  }
}

// Uporaba
fetchData('https://jsonplaceholder.typicode.com/users').then(users => {
  console.log('Uporabniki:', users);
});

fetchData<{ title: string; body: string }>('https://jsonplaceholder.typicode.com/todos/1').then(todo => {
    console.log('Todo', todo)
});

Uporaba prestreznikov za globalno obravnavanje napak

Axios ponuja prestreznike, ki vam omogočajo prestrezanje zahtev in odzivov, preden jih obravnava vaša koda. Prestreznike lahko uporabite za izvajanje globalnega obravnavanja napak, kot je beleženje napak ali prikazovanje sporočil o napakah uporabniku.

axios.interceptors.response.use(
  (response) => response,
  (error) => {
    console.error('Globalni obravnavalec napak:', error);
    // Pokažite sporočilo o napaki uporabniku
    return Promise.reject(error);
  }
);

Uporaba spremenljivk okolja za URL-je API

Da se izognete trdi kodiranju URL-jev API v vaši kodi, lahko uporabite spremenljivke okolja za shranjevanje URL-jev. To olajša konfiguracijo vaše aplikacije za različna okolja, kot so razvojno, preizkusno in produkcijsko okolje.

Primer uporabe datoteke `.env` in paketa `dotenv`.

// .env
API_URL=https://api.example.com
// Namestite dotenv
npm install dotenv
// Uvozite in konfigurirajte dotenv
import * as dotenv from 'dotenv'
dotenv.config()

const apiUrl = process.env.API_URL || 'http://localhost:3000'; // zagotovite privzeto vrednost

async function fetchData(endpoint: string): Promise {
  try {
    const response = await axios.get(`${apiUrl}/${endpoint}`);
    return response.data;
  } catch (error) {
    console.error(`Napaka pri pridobivanju podatkov iz ${apiUrl}/${endpoint}:`, error);
    throw error;
  }
}

Zaključek

Varno tipizirani klici API so bistveni za izgradnjo robustnih, vzdržljivih in sproščenih spletnih aplikacij. TypeScript ponuja zmogljive funkcije, ki vam omogočajo določanje tipov za odzive API, validacijo podatkov med izvajanjem in elegantno obravnavo napak. Z upoštevanjem najboljših praks in tehnik, opisanih v tem priročniku, lahko znatno izboljšate kakovost in zanesljivost svojih interakcij API.

Z uporabo TypeScript in knjižnic, kot sta Axios in Zod, lahko zagotovite, da so vaši klici API varni, vaši podatki so validirani in vaše napake so obravnavane elegantno. To bo vodilo do bolj robustnih in vzdržljivih aplikacij.

Ne pozabite vedno validirati svojih podatkov med izvajanjem, tudi s sistemom tipov TypeScript. API-ji se lahko spremenijo, vaši tipi pa morda niso vedno popolnoma sinhronizirani z dejanskim odzivom API-ja. Z validacijo svojih podatkov med izvajanjem lahko ujamete morebitne težave, preden povzročijo težave v vaši aplikaciji.

Srečno kodiranje!