javascript - Angular: Http vs fetch API


Även om jag förstår sättet Angular gör HTTP-förfrågningar på, föredrar jag att använda den inbyggda Fetch API eftersom jag inte behöver prenumerera och avprenumerera bara för att göra en enkel förfrågan. Jag försökte använda den i min Angular-app och den kastade inga fel, sidan laddades inte om (fortfarande en SPA), allt fungerade bra. Jag antar att det finns en tid och plats för allt.

Det här :

fetch('/api/get_post_by_id/1').then(r => r.json()).then(j => { console.log(j); });

Är enklare än detta:

const obs = this.http.get('/api');
obs.subscribe(() => { ... });
obs.unsubscribe();

I princip är min fråga, är det fel att använda Fetch API när man utvecklar Angular-appar?

Svar #1

Som med alla verktyg du stöter på under utvecklingen kommer varje verktyg att ha fördelar och nackdelar och det är bra att tänka på varför ett verktyg används.

När vi tittar på HttpClient förenklade det ursprungligen röran som var XMLHttpRequest. På samma sätt som $.ajax ursprungligen gjorde det, var HttpClient 'Angular-lösningen'. Det följde idén om att allt är ett observable, vilket har fördelar (du kan kombinera det med andra observables) och nackdelar (det tillför mycket extra).

Fördelar med HttpClient

  • Det gör det enkelt att blanda och kombinera två observables (t.ex. låt oss säga att du har en observable som returnerar flera gånger och en API-förfrågan som returnerar en gång och du vill zipa de två tillsammans, det är väldigt enkelt att göra). Självklart kräver det endast att importera from från rxjs för att omvandla ett löfte till en observable.
  • Om du glömmer att lägga till en abstraktion - att alla förfrågningar går genom ett apiService-lager - kan du fortfarande använda en interceptor för att på ett magiskt sätt uppnå liknande resultat.
  • Det kommer att öka inlärningskurvan för nya Angular-utvecklare, vilket gör ditt jobb mer speciellt.
  • HttpClient gör lite magi åt dig, såsom automatisk omsändning av förfrågningar.
  • Det är redan inkluderat i Angular, så om du behöver stödja 7 år gamla webbläsare som IE11 behöver du inte ladda en polyfill som med fetch.

Fördelar med fetch

Viktigt : All kod relaterad till fetch antar att du skapar en mycket enkel abstraktion (t.ex. apiService i dessa exempel). Detta är samma sak som att sätta upp en interceptor i HttpClient-land.

  • Det är den nya industristandarden. När du väl kan det, kan det användas överallt (troligtvis när Angular och React försvinner - vilket de vid någon punkt kommer att göra - fetch kommer troligen fortfarande att finnas kvar).

  • Det förenklar arbetet med service workers eftersom Request- och Response-objekten är samma som du använder i din vanliga kod.

  • HTTP-förfrågningar kommer vanligtvis att returnera en gång och endast en gång (naturligtvis kan du ladda en fil bit för bit, men det är ett mycket ovanligt undantag från regeln). fetch är byggt kring normen (enda returvärden), inte undantaget (flera returvärden), och returnerar därför ett Promise snarare än en ström-liknande typ. Den fördelen detta medför är att det fungerar bra med alla relevanta nya språkfunktioner såsom async och await. Jämför:

     try {
         const posts = await this.apiService.get('/posts');
         // work with posts
     } catch (error) {
         // handle error
     }
     console.log('this happens **after** the request completes');
    

    med

     this.http.get('/posts')
         .subscribe(posts => {
             // work with posts
         })
         .catch(error => {
             // work with error
         });
     console.log('this happens **before** the request completes');
    

    (självklart kan du också toPromise varje Observable som kommer att slutföras (eller lägga till .pipe(take(1))

  • Det förenklar introduktionen av nya personer. När du ser en begäran såsom

     this.apiService.get('/posts');
    

    en utvecklare från vilket ramverk som helst kan komma och högerklicka på .get och titta på funktionsdefinitionen där saker som en domän och en autentiseringsheader som läggs till kommer att vara tydligt definierade.

    Å andra sidan när en utvecklare ser

     this.http.get('/posts')
    

    de har inget sätt att enkelt upptäcka om och var begäran kan ändras om de inte är medvetna om Angular-specifik magi. Detta är en av anledningarna till att Angular anses ha en brant inlärningskurva.

  • Det finns ingen risk för att det finns magi som du inte är medveten om, såsom automatisk omförsök av förfrågningar som kan leda till att samma förfrågan triggas fyra gånger på servern och att du inte har någon aning om hur det är möjligt.

  • Det är redan inkluderat i webbläsaren - förutsatt att du inte behöver stödja 7 år gamla webbläsare - så det kan resultera i en något mindre paketstorlek.

Oavgjort

  • Jag ser ärligt talat inte hur typer skulle vara en skillnad, eftersom det går att typa ett returvärde från vilken metod som helst. <Model>this.apiService.get('/posts') fungerar alldeles utmärkt.

Slutsats

Personligen skulle jag starkt rekommendera alla att använda fetch med ett abstraktionslager. Det resulterar i mer lättläst kod (även en junior som aldrig har sett async och await kan läsa den) och även om du befinner dig i en ovanlig situation där din apiService måste returnera flera gånger är du ändå helt fri att göra det eftersom du har full kontroll. Och generellt sett bör du endast inte använda standard (fetch) om alternativet erbjuder betydande fördelar. Även om det var en perfekt balans i termer av fördelar och nackdelar är det troligen inte värt att välja en 'ramverksspecifik' lösning.

HttpClient verkar helt enkelt inte erbjuda några konkreta fördelar utöver att spara ett par minuters tid under den initiala projektuppsättningen där du inte behöver sätta upp ett abstraktionslager för API-förfrågningar.

Svar #2

this.http.get('/api').subscribe(j => console.log(j)); 

Du gjorde det för komplicerat, ovan är allt du behöver och det är liknande den kod du har för window.fetch. Du kan använda den generiska versionen och den kommer också att vara typad enligt det förväntade gränssnittet vilket gör det ännu enklare.

this.http.get<IModel>('/api').subscribe(j => console.log(j));

Det finns inget behov av unsubscribe och du behöver endast pipe + map om du vill omvandla resultatet i förväg. Att kalla på json() var nödvändigt för det ”gamla” HttpModule som har ersatts med (tekniskt utökat av) HttpClient från och med version 4.3

Och om du fortfarande föredrar Promise framför ett Observable kan du alltid kalla toPromise().

this.http.get('/api').toPromise().then(j => console.log(j)); 

Se även HttpClient

är det fel att använda Fetch API när man utvecklar Angular-appar?

Det är inte fel men det finns skäl att inte göra det. Du kan injicera HttpClient och skriva omfattande enhetstester för olika scenarier, URL:er, HTTP-verb osv. Att göra samma sak om du har använt window.fetch i hela din kod blir mycket svårare. HttpClient är också rikare eftersom du kan använda typ systemet för dina resultat. Observables är också mer funktionsrika än Promises och detta kan vara användbart i mer komplexa scenarier som att sekvensera anrop när man hanterar flera mikroservice eller avbryta ett anrop om ytterligare användarinmatning tas emot.

Så det finns flera anledningar att använda HttpClient och jag kan inte komma på en enda anledning att inte göra det förutom att det är en liten inlärningskurva.

Relaterade artiklar