Configuración de cadena de consulta utilizando la solicitud GET Fetch

148

Estoy tratando de usar la nueva API Fetch :

Estoy haciendo una GETsolicitud como esta:

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

Sin embargo, no estoy seguro de cómo agregar una cadena de consulta a la GETsolicitud. Idealmente, quiero poder hacer una GETsolicitud a un me URLgusta:

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

En jQuerypodría hacer esto pasando {order_id: 1}como dataparámetro de $.ajax(). ¿Hay una manera equivalente de hacer eso con lo nuevo Fetch API?

mylescc
fuente

Respuestas:

173

Actualización de marzo de 2017:

La compatibilidad con URL.searchParams ha aterrizado oficialmente en Chrome 51, pero otros navegadores aún requieren un polyfill .


La forma oficial de trabajar con parámetros de consulta es simplemente agregarlos a la URL. De la especificación , este es un ejemplo:

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

Sin embargo, no estoy seguro de que Chrome sea compatible con la searchParamspropiedad de una URL (en el momento de la escritura), por lo que es posible que desee utilizar una biblioteca de terceros o una solución roll-your-own .

Actualización de abril de 2018:

Con el uso del constructor URLSearchParams , puede asignar una matriz 2D o un objeto y simplemente asignarlo al en url.searchlugar de recorrer todas las teclas y agregarlas

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)

URLSearchParamsNota al margen : también está disponible en NodeJS

const { URL, URLSearchParams } = require('url');
CodificaciónIntriga
fuente
1
También hay developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/… , aunque a partir de este escrito todavía está avanzando a través de las especificaciones, y aún no está bien respaldado. Y la API se parece más a Java que a JS. : /
ericsoco
1
Consulte caniuse.com/#feat=urlsearchparams para obtener asistencia sobre la URLSearchParamsinterfaz; Me supongo (aunque no estoy 100% seguro) que los navegadores en rojo no son exactamente los navegadores para los que URLlos objetos no tendrá la .searchParamspropiedad. Es importante destacar que Edge todavía no tiene soporte.
Mark Amery
1
De la documentación: "Tenga en cuenta que el uso de una instancia URLSearchParams está en desuso; pronto los navegadores solo usarán una cadena USVString para el init". fuente: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/…
pakman
1
new URLSearchParamsno parece funcionar correctamente con Arraypropiedades. Me esperaba que para convertir la propiedad array: [1, 2]a array[]=1&array[]=2, pero convertí a array=1,2. El uso manual del appendmétodo resulta en array=1&array=2, pero tendría que iterar sobre el objeto params, y hacerlo solo para los tipos de matriz, no muy ergonómicos.
erandros
1
De hecho, se agregó por error :) 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
fuente
26

Como ya se respondió, esto es por especificación no posible con el fetch-API, todavía. Pero tengo que tener en cuenta:

Si estás encendido node, ahí está el querystringpaquete. Puede stringificar / analizar objetos / cadenas de consulta:

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

... luego añádelo a la url para solicitarlo.


Sin embargo, el problema con lo anterior es que siempre tiene que anteponer un signo de interrogación ( ?). Entonces, otra forma es usar el parsemétodo del urlpaquete de nodos y hacerlo de la siguiente manera:

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

Ver queryen https://nodejs.org/api/url.html#url_url_format_urlobj

Esto es posible, ya que internamente solo esto :

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

Un enfoque conciso de ES6:

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

La función toString () de URLSearchParam convertirá los argumentos de consulta en una cadena que se puede agregar a la URL. En este ejemplo, toString () se llama implícitamente cuando se concatena con la URL.

IE no es compatible con esta función, pero hay polyfills disponibles.

Scotty Jamison
fuente
9

Puede usar #stringifydesde la cadena de consulta

import { stringify } from 'query-string';

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

Quizás esto es mejor:

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

encodeQueryString - codifica un objeto como parámetros de cadena de consulta

/**
 * 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
fuente
5

Sé que esto indica lo absolutamente obvio, pero creo que vale la pena agregar esto como respuesta, ya que es el más simple de todos:

var orderId = 1;
var request = new Request({
  url: 'http://myapi.com/orders?order_id=' + orderId,
  method: 'GET'
});
fetch(request);
Evert
fuente
77
Vale la pena calificar que esto solo funciona de manera confiable con tipos enteros. Si utiliza cadenas, especialmente los suministrados por el usuario (como criterios de búsqueda), entonces usted tiene que escapar de la cadena, de lo contrario puede obtener resultados extraños personajes como si /, +o &aparecer en la cadena.
Malvinoso
El uso del objeto Solicitud puede ayudar, especialmente si desea usar una función para construir la solicitud y luego entregarla a la llamada fetch (), pero no creo que usarla sea "absolutamente obvio". Además, la url no debe especificarse en el objeto literal de las opciones de configuración; se debe pasar por separado como el primer parámetro al constructor de Solicitud ( developer.mozilla.org/en-US/docs/Web/API/Request/Request ).
Gen1-1
3

Los literales de plantilla también son una opción válida aquí y brindan algunos beneficios.

Puede incluir cadenas sin formato, números, valores booleanos, etc.

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

Puedes incluir variables:

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

Puede incluir lógica y funciones:

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

En cuanto a estructurar los datos de una cadena de consulta más grande, me gusta usar una matriz concatenada a una cadena. Me resulta más fácil de entender que algunos de los otros 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
fuente
9
Debe tener mucho cuidado con este método porque no escapa de las cadenas primero. Entonces, si obtiene una variable que contiene un carácter como +o &entonces no funcionará como se esperaba y terminará con diferentes parámetros y valores a lo que pensaba.
Malvinoso
-1

Solo estaba trabajando con fetchModule de Nativescript y descubrí mi propia solución usando la manipulación de cadenas. Agregue la cadena de consulta bit a bit a la url. Aquí hay un ejemplo donde la consulta se pasa como un 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.
}

Probé esto en varios parámetros de consulta y funcionó de maravilla :) Espero que esto ayude a alguien.

Amjad Abujamous
fuente
1
Este es un buen ejemplo de por qué debería usar bibliotecas de terceros: su código podría estar funcionando bien, pero alguien ya lo hizo mucho mejor
refaelio