Установка строки запроса с помощью запроса Fetch GET


166

Я пытаюсь использовать новый Fetch API :

Я делаю такой GETзапрос:

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

Однако я не знаю, как добавить в запрос строку GETзапроса. В идеале я хочу иметь возможность сделать GETзапрос на URLлайк:

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

В jQueryя мог бы сделать это, передав {order_id: 1}в качестве dataпараметра $.ajax(). Есть ли эквивалентный способ сделать это с новым Fetch API?

Ответы:


192

Обновление март 2017 г .:

Поддержка URL.searchParams официально появилась в Chrome 51, но для других браузеров по-прежнему требуется полифил .


Официальный способ работы с параметрами запроса , это просто добавить их на URL. Из спецификации это пример:

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

Однако я не уверен, что Chrome поддерживает searchParamsсвойство URL-адреса (на момент написания), поэтому вы можете использовать стороннюю библиотеку или самостоятельное решение .

Обновление апреля 2018:

С помощью конструктора URLSearchParams вы можете назначить 2D-массив или объект и просто назначить его url.searchвместо того, чтобы перебирать все ключи и добавлять их.

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: URLSearchParamsтакже доступно в NodeJS

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

1
Также есть developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/… , хотя на момент написания он все еще проходит через спецификацию и еще не поддерживается. И API больше похож на Java, чем на JS. : /
ericsoco

1
См. Caniuse.com/#feat=urlsearchparams для поддержки URLSearchParamsинтерфейса; Я бы предположил (хотя я не уверен на 100%), что браузеры, выделенные красным, это именно те браузеры, для которых URLобъекты не будут иметь .searchParamsсвойства. Важно отметить, что Edge по-прежнему не имеет поддержки.
Марк Эмери

1
Из документации: «Обратите внимание, что использование экземпляра URLSearchParams устарело; скоро браузеры будут просто использовать USVString для инициализации». источник: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/…
pakman

1
new URLSearchParamsпохоже, не работает правильно со Arrayсвойствами. Я ожидал, что он преобразует свойство array: [1, 2]в array[]=1&array[]=2, но преобразовал в array=1,2. Ручное использование этого appendметода действительно приводит array=1&array=2, но мне пришлось бы перебирать объект params и делать это только для типов массивов, что не очень эргономично.
erandros 07

1
Это действительно было добавлено по ошибке :) github.com/mdn/sprints/issues/2856
CodingIntrigue

54

Краткий подход ES6:

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

Функция URLSearchParams toString () преобразует аргументы запроса в строку, которую можно добавить к URL-адресу. В этом примере toString () вызывается неявно при объединении с URL-адресом. Вероятно, вы захотите вызвать toString () явно, чтобы улучшить читаемость.

IE не поддерживает URLSearchParams (или выборки), но есть polyfills доступны .

Если вы используете узел, вы можете добавить API выборки через такой пакет, как node-fetch . URLSearchParams поставляется с node и может быть найден как глобальный объект, начиная с версии 10. В более старой версии вы можете найти его по адресу require('url').URLSearchParams.


2
Спасибо, что поделился. Я думаю, это должен быть принятый ответ. Его попросили передать параметры в API выборки, и хотя это невозможно, этот ответ чертовски близок к тому, как это будет выглядеть по структуре.
Джесси Реза Хорасани,

34
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)
  });

27

Как уже было fetchсказано, это пока невозможно с -API. Но я должен отметить:

Если да node, то querystringпосылка есть. Он может преобразовывать / анализировать объекты / строки запросов:

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

... затем просто добавьте его к URL-адресу для запроса.


Однако проблема в том, что вы всегда должны ставить вопросительный знак ( ?). Итак, другой способ - использовать parseметод из urlпакета узлов и сделать это следующим образом:

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

См queryна https://nodejs.org/api/url.html#url_url_format_urlobj

Это возможно, так как внутри он делает следующее :

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


5

Может так лучше:

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 - закодировать объект как параметры строки запроса

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

Я знаю, что это абсолютно очевидно, но я считаю, что стоит добавить это в качестве ответа, поскольку это самый простой из всех:

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

8
Стоит отметить, что это надежно работает только с целочисленными типами. Если вы используете строки, особенно предоставленные пользователем (например, критерии поиска), вы должны экранировать строку, в противном случае вы можете получить нечетные результаты, если такие символы, как /, +или &появятся в строке.
Malvineous

Использование объекта Request может помочь, особенно если вы хотите использовать функцию для создания запроса, а затем передать его вызову fetch (), но я не думаю, что его использование «абсолютно очевидно». Кроме того, URL-адрес не должен указываться в литерале объекта параметров конфигурации; его следует передать отдельно как 1-й параметр конструктору запроса ( developer.mozilla.org/en-US/docs/Web/API/Request/Request ).
Gen1-1,

3

Шаблонные литералы также являются допустимым вариантом и дают несколько преимуществ.

Вы можете включать необработанные строки, числа, логические значения и т. Д .:

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

Вы можете включать переменные:

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

Вы можете включить логику и функции:

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

Что касается структурирования данных более крупной строки запроса, мне нравится использовать массив, соединенный со строкой. Мне это легче понять, чем некоторые другие методы:

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

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

9
Вы должны быть очень осторожны с этим методом, потому что он не выполняет экранирование строк сначала. Так что, если вы получите переменную, содержащую такой символ, как +или, &тогда она не будет работать должным образом, и вы получите параметры и значения, отличные от того, что вы думали.
Malvineous

1

Решение без внешних пакетов

для выполнения запроса GET с использованием API выборки я работал над этим решением, которое не требует установки пакетов.

это пример вызова API карты Google

// encode to scape spaces
const esc = encodeURIComponent;
const url = 'https://maps.googleapis.com/maps/api/geocode/json?';
const params = { 
    key: "asdkfñlaskdGE",
    address: "evergreen avenue",
    city: "New York"
};
// this line takes the params object and builds the query string
const query = Object.keys(params).map(k => `${esc(k)}=${esc(params[k])}`).join('&')
const res = await fetch(url+query);
const googleResponse = await res.json()

не стесняйтесь копировать этот код и вставлять его в консоль, чтобы увидеть, как он работает !!

сгенерированный URL-адрес выглядит примерно так:

https://maps.googleapis.com/maps/api/geocode/json?key=asdkf%C3%B1laskdGE&address=evergreen%20avenue&city=New%20York

это то, что я искал, прежде чем решил это написать, наслаждайтесь: D


0

Просто работал с fetchModule Nativescript и выяснил свое собственное решение, используя манипуляции со строками. Добавляйте строку запроса к URL-адресу по крупицам. Вот пример, в котором запрос передается как объект 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.
}

Я тестировал это на множестве параметров запроса, и это сработало как шарм :) Надеюсь, это кому-то поможет.


1
Это хороший пример того, почему вы должны использовать сторонние библиотеки - ваш код может работать нормально, но кто-то уже сделал это намного лучше
refaelio

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.