Définition de la chaîne de requête à l'aide de la requête Fetch GET

149

J'essaye d'utiliser la nouvelle API Fetch :

Je fais une GETdemande comme celle-ci:

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

Cependant, je ne sais pas comment ajouter une chaîne de requête à la GETdemande. Idéalement, je veux pouvoir faire une GETdemande à un URLlike:

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

Dans jQueryje pourrais le faire en passant {order_id: 1}comme dataparamètre de $.ajax(). Y a-t-il une manière équivalente de faire cela avec le nouveau Fetch API?

mylescc
la source

Réponses:

174

Mise à jour mars 2017:

Le support d' URL.searchParams a officiellement atterri dans Chrome 51, mais d'autres navigateurs nécessitent toujours un polyfill .


La manière officielle de travailler avec les paramètres de requête consiste simplement à les ajouter à l'URL. D'après les spécifications , voici un exemple:

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(/* … */)

Cependant, je ne suis pas sûr que Chrome prenne en charge la searchParamspropriété d'une URL (au moment de la rédaction de cet article), vous pouvez donc utiliser une bibliothèque tierce ou une solution personnalisée .

Mise à jour avril 2018:

Avec l'utilisation du constructeur URLSearchParams, vous pouvez attribuer un tableau 2D ou un objet et l'attribuer simplement au au url.searchlieu de boucler sur toutes les clés et de les ajouter

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)

Sidenote: URLSearchParamsest également disponible dans NodeJS

const { URL, URLSearchParams } = require('url');
CodageIntrigue
la source
1
Il y a aussi developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/... , mais au moment d'écrire ces lignes, il est toujours en train de passer par les spécifications et n'est pas encore bien pris en charge. Et l'API ressemble plus à Java qu'à JS. : /
ericsoco
1
Voir caniuse.com/#feat=urlsearchparams pour la prise en charge de l' URLSearchParamsinterface; Je suppose (bien que je ne sois pas certain à 100%) que les navigateurs en rouge sont exactement les navigateurs pour lesquels les URLobjets n'auront pas la .searchParamspropriété. Surtout, Edge n'a toujours pas de support.
Mark Amery
1
Dans la documentation: "Notez que l'utilisation d'une instance URLSearchParams est obsolète; bientôt, les navigateurs utiliseront simplement une chaîne USVString pour l'init." source: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/…
pakman
1
new URLSearchParamsne semble pas fonctionner correctement avec les Arraypropriétés. Je m'attendais à ce qu'il convertisse la propriété array: [1, 2]en array[]=1&array[]=2, mais je l'ai convertie en array=1,2. Utiliser manuellement la appendméthode de celui-ci entraîne array=1&array=2, mais je devrais itérer sur l'objet params, et le faire uniquement pour les types de tableaux, pas très ergonomiques.
erandros
1
Il a en effet été ajouté par erreur :) 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)
  });
Sudharshan
la source
26

Comme déjà répondu, cela n'est pas possible selon les spécifications avec le fetch-API, pour le moment. Mais je dois noter:

Si vous êtes sur node, voici le querystringpackage. Il peut stringifier / analyser des objets / des chaînes de requêtes:

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

... puis ajoutez-le simplement à l'URL pour demander.


Cependant, le problème avec ce qui précède est que vous devez toujours ajouter un point d'interrogation ( ?). Donc, une autre façon est d'utiliser la parseméthode du urlpackage de nœuds et de le faire comme suit:

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

Voir queryà https://nodejs.org/api/url.html#url_url_format_urlobj

Ceci est possible, car il le fait en interne juste ceci :

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

Une approche ES6 concise:

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

La fonction toString () d' URLSearchParams convertit les arguments de la requête en une chaîne qui peut être ajoutée à l'URL. Dans cet exemple, toString () est appelé implicitement lorsqu'il est concaténé avec l'URL.

IE ne prend pas en charge URLSearchParams, mais des polyfills sont disponibles.

Si vous utilisez node, vous pouvez trouver URLSearchParams en tant qu'objet global depuis la version 10. Dans l'ancienne version, vous pouvez le trouver à la require('url').URLSearchParamsplace. L'API d'extraction réelle ne fait pas partie du nœud et doit être ajoutée via un package, tel que node-fetch .

Scotty Jamison
la source
9

Vous pouvez utiliser à #stringifypartir de la chaîne de requête

import { stringify } from 'query-string';

fetch(`https://example.org?${stringify(params)}`)
Hirurg103
la source
5

Peut-être que c'est mieux:

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);
});
Bin HOU
la source
5

encodeQueryString - encode un objet en tant que paramètres de chaîne de requête

/**
 * 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"
ChaseMoskal
la source
5

Je sais que c'est une évidence absolue, mais je pense que cela vaut la peine d'ajouter ceci comme réponse car c'est la plus simple de toutes:

var orderId = 1;
var request = new Request({
  url: 'http://myapi.com/orders?order_id=' + orderId,
  method: 'GET'
});
fetch(request);
Evert
la source
7
Il convient de préciser que cela ne fonctionne de manière fiable qu'avec les types entiers. Si vous utilisez des chaînes, en particulier ceux fournis par l' utilisateur (comme critères de recherche) alors vous devez échapper à la chaîne, sinon vous pouvez obtenir des résultats étranges si des personnages comme /, +ou &apparaissent dans la chaîne.
Malvineous
L'utilisation de l'objet Request peut aider, en particulier si vous voulez utiliser une fonction pour construire la requête et la remettre ensuite à l'appel fetch (), mais je ne pense pas que son utilisation soit "absolument évidente". De plus, l'url ne doit pas être spécifiée dans le littéral objet des options de configuration; il doit être passé séparément en tant que 1er paramètre au constructeur Request ( developer.mozilla.org/en-US/docs/Web/API/Request/Request ).
Gen1-1
3

Les littéraux de modèle sont également une option valable ici et offrent quelques avantages.

Vous pouvez inclure des chaînes brutes, des nombres, des valeurs booléennes, etc.:

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

Vous pouvez inclure des variables:

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

Vous pouvez inclure la logique et les fonctions:

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

En ce qui concerne la structuration des données d'une chaîne de requête plus grande, j'aime utiliser un tableau concaténé en une chaîne. Je trouve cela plus facile à comprendre que certaines des autres méthodes:

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

let request = new Request(`https://example.com/?${queryString}`, {
  method: 'GET'
});
Pat Kearns
la source
9
Vous devez être très prudent avec cette méthode car elle n'échappe pas d'abord les chaînes par URL. Donc, si vous obtenez une variable contenant un caractère comme +ou &alors cela ne fonctionnera pas comme prévu et vous vous retrouverez avec des paramètres et des valeurs différents de ce que vous pensiez.
Malvineous
-1

Je travaillais juste avec fetchModule de Nativescript et j'ai trouvé ma propre solution en utilisant la manipulation de chaînes. Ajoutez la chaîne de requête petit à petit à l'URL. Voici un exemple où la requête est passée en tant qu'objet json (query = {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.
}

J'ai testé cela sur plusieurs paramètres de requête et cela a fonctionné comme un charme :) J'espère que cela aide quelqu'un.

Amjad Abujamous
la source
1
Ceci est un bon exemple de la raison pour laquelle vous devriez utiliser des bibliothèques tierces - votre code fonctionne peut-être bien, mais quelqu'un l'a déjà fait beaucoup mieux
refaelio