Ustawianie ciągu zapytania przy użyciu żądania Fetch GET


148

Próbuję użyć nowego interfejsu API pobierania :

Składam taką GETprośbę:

var request = new Request({
  url: 'http://myapi.com/orders',
  method: 'GET'
});
fetch(request);

Jednak nie jestem pewien, jak dodać ciąg zapytania do GETżądania. Idealnie, chciałbym móc wysłać GETprośbę do URLpolubienia:

'http://myapi.com/orders?order_id=1'

W jQuerymógłbym to zrobić przekazując {order_id: 1}jako dataparametr $.ajax(). Czy istnieje równoważny sposób na zrobienie tego z nowym Fetch API?

Odpowiedzi:


173

Aktualizacja marzec 2017:

Obsługa URL.searchParams oficjalnie trafiła do Chrome 51, ale inne przeglądarki nadal wymagają wypełnienia polyfill .


Oficjalny sposób pracy z parametrami zapytania jest tylko, aby dodać je na adres URL. Ze specyfikacji jest to przykład:

var url = new URL("https://geo.example.org/api"),
    params = {lat:35.696233, long:139.570431}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
fetch(url).then(/* … */)

Jednak nie jestem pewien, czy Chrome obsługuje searchParamswłaściwość adresu URL (w momencie pisania), więc możesz chcieć użyć biblioteki innej firmy lub własnego rozwiązania .

Aktualizacja kwiecień 2018:

Za pomocą konstruktora URLSearchParams możesz przypisać tablicę 2D lub obiekt i po prostu przypisać to do url.searchzamiast zapętlania wszystkich kluczy i dołączyć je

var url = new URL('https://sl.se')

var params = {lat:35.696233, long:139.570431} // or:
var params = [['lat', '35.696233'], ['long', '139.570431']]

url.search = new URLSearchParams(params).toString();

fetch(url)

Uwaga dodatkowa: URLSearchParamsjest również dostępna w NodeJS

const { URL, URLSearchParams } = require('url');

1
Istnieje również developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/… , chociaż w chwili pisania tego tekstu wciąż przechodzi przez specyfikację i nie jest jeszcze dobrze obsługiwany. A API bardziej przypomina Javę niż JS. : /
ericsoco

1
Zobacz caniuse.com/#feat=urlsearchparams, aby uzyskać pomoc dotyczącą URLSearchParamsinterfejsu; Chciałbym założyć, (choć nie jestem w 100% pewien), że przeglądarek na czerwono są dokładnie przeglądarek, dla których URLobiekty nie będą miały .searchParamswłaściwości. Co ważne, Edge nadal nie ma wsparcia.
Mark Amery,

1
Z dokumentacji: „Zauważ, że używanie instancji URLSearchParams jest przestarzałe; wkrótce przeglądarki będą po prostu używać USVString do inicjalizacji”. źródło: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/…
pakman

1
new URLSearchParamsnie wydaje się działać poprawnie z Arraywłaściwościami. Spodziewałem się, że przekonwertuje właściwość array: [1, 2]na array[]=1&array[]=2, ale przekonwertowałem ją na array=1,2. Ręczne użycie tej appendmetody skutkuje array=1&array=2, ale musiałbym iterować po obiekcie params i zrobić to tylko dla typów tablicowych, niezbyt ergonomicznych.
erandros

1
Rzeczywiście został dodany omyłkowo :) github.com/mdn/sprints/issues/2856
CodingIntrigue

30
let params = {
  "param1": "value1",
  "param2": "value2"
};

let query = Object.keys(params)
             .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
             .join('&');

let url = 'https://example.com/search?' + query;

fetch(url)
  .then(data => data.text())
  .then((text) => {
    console.log('request succeeded with JSON response', text)
  }).catch(function (error) {
    console.log('request failed', error)
  });

26

Jak już odpowiedzieliśmy, zgodnie ze specyfikacją nie jest to jeszcze możliwe z fetch-API. Ale muszę zauważyć:

Jeśli jesteś włączony node, jest querystringpakiet. Potrafi stringifikować / analizować obiekty / kwerendy:

var querystring = require('querystring')
var data = { key: 'value' }
querystring.stringify(data) // => 'key=value'

... a następnie po prostu dołącz go do adresu URL, aby zażądać.


Jednak problem z powyższym polega na tym, że zawsze musisz poprzedzić znak zapytania ( ?). Tak więc innym sposobem jest użycie parsemetody z urlpakietu nodes i zrobienie tego w następujący sposób:

var url = require('url')
var data = { key: 'value' }
url.format({ query: data }) // => '?key=value'

Zobacz queryna https://nodejs.org/api/url.html#url_url_format_urlobj

Jest to możliwe, ponieważ robi to wewnętrznie tylko w ten sposób :

search = obj.search || (
    obj.query && ('?' + (
        typeof(obj.query) === 'object' ?
        querystring.stringify(obj.query) :
        String(obj.query)
    ))
) || ''

25

Zwięzłe podejście ES6:

fetch('https://example.com?' + new URLSearchParams({
    foo: 'value',
    bar: 2,
}))

Funkcja toString () w URLSearchParams przekształci argumenty zapytania w ciąg znaków, który można dołączyć do adresu URL. W tym przykładzie toString () jest wywoływana niejawnie, gdy zostanie połączona z adresem URL.

IE nie obsługuje parametrów URLSearchParams, ale są dostępne polifile .

Jeśli używasz węzła, możesz znaleźć URLSearchParams jako obiekt globalny od wersji 10. W starszej wersji możesz go znaleźć require('url').URLSearchParamszamiast. Rzeczywisty interfejs API pobierania nie jest częścią węzła i należy go dodać za pośrednictwem pakietu, na przykład pobierania węzła .



5

Może tak jest lepiej:

const withQuery = require('with-query');

fetch(withQuery('https://api.github.com/search/repositories', {
  q: 'query',
  sort: 'stars',
  order: 'asc',
}))
.then(res => res.json())
.then((json) => {
  console.info(json);
})
.catch((err) => {
  console.error(err);
});

5

encodeQueryString - zakoduj obiekt jako parametry querystring

/**
 * Encode an object as url query string parameters
 * - includes the leading "?" prefix
 * - example input — {key: "value", alpha: "beta"}
 * - example output — output "?key=value&alpha=beta"
 * - returns empty string when given an empty object
 */
function encodeQueryString(params) {
    const keys = Object.keys(params)
    return keys.length
        ? "?" + keys
            .map(key => encodeURIComponent(key)
                + "=" + encodeURIComponent(params[key]))
            .join("&")
        : ""
}

encodeQueryString({key: "value", alpha: "beta"})
 //> "?key=value&alpha=beta"

5

Wiem, że jest to absolutnie oczywiste, ale czuję, że warto dodać to jako odpowiedź, ponieważ jest to najprostsze ze wszystkich:

var orderId = 1;
var request = new Request({
  url: 'http://myapi.com/orders?order_id=' + orderId,
  method: 'GET'
});
fetch(request);

7
Warto zaznaczyć, że działa to niezawodnie tylko w przypadku typów całkowitych. Jeśli używasz ciągi, zwłaszcza te, dostarczone przez użytkownika (np kryteriów wyszukiwania), potem trzeba uciec ciąg, w przeciwnym razie można dostać dziwne wyniki, jeśli znaki podoba /, +czy &pojawiają się w ciągu.
Malvineous

Użycie obiektu Request może pomóc, zwłaszcza jeśli chcesz użyć funkcji do zbudowania żądania, a następnie przekazać to wywołaniu funkcji fetch (), ale nie sądzę, aby używanie go było „absolutnie oczywiste”. Ponadto adres URL nie powinien być określany w literale obiektu opcji konfiguracyjnych; powinien być przekazany osobno jako pierwszy parametr do konstruktora żądania ( developer.mozilla.org/en-US/docs/Web/API/Request/Request ).
Gen1-1

3

Literały szablonów są również tutaj poprawną opcją i zapewniają kilka korzyści.

Możesz dołączyć nieprzetworzone ciągi, liczby, wartości logiczne itp .:

    let request = new Request(`https://example.com/?name=${'Patrick'}&number=${1}`);

Możesz dołączyć zmienne:

    let request = new Request(`https://example.com/?name=${nameParam}`);

Możesz dołączyć logikę i funkcje:

    let request = new Request(`https://example.com/?name=${nameParam !== undefined ? nameParam : getDefaultName() }`);

Jeśli chodzi o tworzenie struktury danych w większym ciągu zapytania, lubię używać tablicy połączonej z ciągiem. Jest to dla mnie łatwiejsze do zrozumienia niż niektóre inne metody:

let queryString = [
  `param1=${getParam(1)}`,
  `param2=${getParam(2)}`,
  `param3=${getParam(3)}`,
].join('&');

let request = new Request(`https://example.com/?${queryString}`, {
  method: 'GET'
});

9
Musisz być bardzo ostrożny z tą metodą, ponieważ najpierw nie powoduje ona zmiany znaczenia w adresie URL. Więc jeśli otrzymasz zmienną, która zawiera znak taki jak +lub, &to nie będzie działać zgodnie z oczekiwaniami, a otrzymasz inne parametry i wartości niż myślisz.
Malvineous

-1

Pracowałem tylko z fetchModule firmy Nativescript i wymyśliłem własne rozwiązanie za pomocą operacji na ciągach znaków. Dołączaj ciąg zapytania bit po bicie do adresu URL. Oto przykład, w którym zapytanie jest przekazywane jako obiekt json (zapytanie = {order_id: 1}):

function performGetHttpRequest(fetchLink='http://myapi.com/orders', query=null) {
    if(query) {
        fetchLink += '?';
        let count = 0;
        const queryLength = Object.keys(query).length;
        for(let key in query) {
            fetchLink += key+'='+query[key];
            fetchLink += (count < queryLength) ? '&' : '';
            count++;
        }
    }
    // link becomes: 'http://myapi.com/orders?order_id=1'
    // Then, use fetch as in MDN and simply pass this fetchLink as the url.
}

Przetestowałem to na wielu parametrach zapytania i zadziałało jak urok :) Mam nadzieję, że to komuś pomoże.


1
To jest dobry przykład, dlaczego powinieneś używać bibliotek innych firm - Twój kod może działać dobrze, ale ktoś już zrobił to znacznie lepiej
refaelio

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.