Definindo a sequência de consultas usando a solicitação Fetch GET

148

Estou tentando usar a nova API de busca :

Estou fazendo uma GETsolicitação como esta:

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

No entanto, não tenho certeza de como adicionar uma string de consulta à GETsolicitação. Idealmente, quero poder fazer uma GETsolicitação para um URLlike:

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

Em jQueryeu poderia fazer isso passando {order_id: 1}como o dataparâmetro de $.ajax(). Existe uma maneira equivalente de fazer isso com o novo Fetch API?

mylescc
fonte

Respostas:

173

Atualização em março de 2017:

O suporte ao URL.searchParams chegou oficialmente ao Chrome 51, mas outros navegadores ainda exigem um polyfill .


A maneira oficial de trabalhar com parâmetros de consulta é apenas adicioná-los ao URL. A partir da especificação , este é um exemplo:

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

No entanto, eu não tenho certeza Chrome suporta a searchParamspropriedade de uma URL (no momento da escrita), de modo que você pode querer ou uso uma biblioteca de terceiros ou solução roll-seu-próprio .

Atualização em abril de 2018:

Com o uso do construtor URLSearchParams, você pode atribuir uma matriz 2D ou um objeto e atribuir isso ao url.searchinvés de repetir todas as chaves e anexá-las

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: URLSearchParamstambém está disponível no NodeJS

const { URL, URLSearchParams } = require('url');
CodingIntrigue
fonte
1
Há também developer.mozilla.org/pt-BR/docs/Web/API/URLSearchParams/… , embora, até o momento desta redação, ele ainda esteja passando pelas especificações e ainda não seja bem suportado. E a API é mais parecida com Java do que JS. : /
ericsoco 14/09
1
Consulte caniuse.com/#feat=urlsearchparams para obter suporte para a URLSearchParamsinterface; Eu supor (embora eu não estou 100% certo) que os navegadores em vermelho não são exatamente os navegadores para os quais URLobjetos não têm a .searchParamspropriedade. Importante, o Edge ainda não tem suporte.
Mark Amery
1
Na documentação: "Observe que o uso de uma instância URLSearchParams está obsoleto; em breve, os navegadores usarão apenas USVString para o init." fonte: developer.mozilla.org/pt-BR/docs/Web/API/URLSearchParams/…
pakman
1
new URLSearchParamsparece não funcionar corretamente com Arraypropriedades. Eu esperava que ele convertesse a propriedade array: [1, 2]em array[]=1&array[]=2, mas a converti em array=1,2. O uso manual do appendmétodo resulta array=1&array=2, mas eu teria que repetir o objeto params e fazer isso apenas para tipos de matriz, não muito ergonômicos.
erandros
1
De fato, foi adicionado com erro :) github.com/mdn/sprints/issues/2856
CodingIntrigue 27/02
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
fonte
26

Como já foi respondido, isso é por especificação não possível com o fetch especificação -API. Mas tenho que observar:

Se você estiver node, há o querystringpacote. Pode stringify / analisar objetos / querystrings:

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

... basta anexá-lo ao URL para solicitar.


No entanto, o problema com o exposto acima é que você sempre deve preceder um ponto de interrogação ( ?). Portanto, outra maneira é usar o parsemétodo do urlpacote nodes e fazer o seguinte:

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

Veja queryem https://nodejs.org/api/url.html#url_url_format_urlobj

Isso é possível, pois ele faz internamente exatamente isso :

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

Uma abordagem concisa do ES6:

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

A função toString () do URLSearchParam converterá os argumentos da consulta em uma sequência que pode ser anexada ao URL. Neste exemplo, toString () é chamado implicitamente quando é concatenado com a URL.

O IE não suporta esse recurso, mas existem polyfills disponíveis.

Scotty Jamison
fonte
9

Você pode usar #stringifyda string de consulta

import { stringify } from 'query-string';

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

Talvez seja melhor:

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
fonte
5

encodeQueryString - codifica um objeto como parâmetros de 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"
ChaseMoskal
fonte
5

Sei que isso é absolutamente óbvio, mas acho que vale a pena adicionar isso como resposta, pois é o mais simples de todos:

var orderId = 1;
var request = new Request({
  url: 'http://myapi.com/orders?order_id=' + orderId,
  method: 'GET'
});
fetch(request);
Evert
fonte
7
Vale a pena qualificar que isso só funciona de maneira confiável com tipos inteiros. Se você usar cordas, especialmente aqueles fornecidos pelo usuário (como critérios de pesquisa), então você tem que escapar da cadeia, caso contrário, você pode obter resultados estranhos se personagens como /, +ou &aparecer na string.
Malvineous
O uso do objeto Request pode ajudar, especialmente se você deseja usar uma função para criar a solicitação e depois entregá-la à chamada fetch (), mas não acho que o uso seja "absolutamente óbvio". Além disso, o URL não deve ser especificado no objeto literal das opções de configuração; ele deve ser passado separadamente como o primeiro parâmetro para o construtor Request ( developer.mozilla.org/en-US/docs/Web/API/Request/Request ).
Gen1-1
3

Os literais de modelo também são uma opção válida aqui e fornecem alguns benefícios.

Você pode incluir strings, números, valores booleanos, etc:

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

Você pode incluir variáveis:

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

Você pode incluir lógica e funções:

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

Quanto a estruturar os dados de uma string de consulta maior, eu gosto de usar uma matriz concatenada em uma string. Acho mais fácil entender do que alguns dos outros métodos:

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

let request = new Request(`https://example.com/?${queryString}`, {
  method: 'GET'
});
Pat Kearns
fonte
9
Você precisa ter muito cuidado com esse método, porque ele não escapa URL das seqüências primeiro. Portanto, se você obtiver uma variável que contenha um caractere semelhante +ou &não, ela não funcionará conforme o esperado e você terminará com parâmetros e valores diferentes do que pensava.
Malvineous
-1

Estava trabalhando com o fetchModule do Nativescript e descobri minha própria solução usando manipulação de string. Anexe a string de consulta pouco a pouco ao URL. Aqui está um exemplo em que a consulta é passada como um objeto 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.
}

Eu testei isso em vários parâmetros de consulta e funcionou como um encanto :) Espero que isso ajude alguém.

Amjad Abujamous
fonte
1
Este é um bom exemplo de por que você deve usar bibliotecas de terceiros - seu código pode estar funcionando bem, mas alguém já o fez muito melhor
refaelio