Встановлення рядка запиту за допомогою Fetch GET-запиту


149

Я намагаюся використовувати новий 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?

Відповіді:


174

Оновлення березня 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 для init." Джерело: 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, але мені доведеться перебирати об’єкт парам, і робити це лише для типів масивів, не дуже ергономічних.
ерандрос

1
Це дійсно було додано помилково: github.com/mdn/sprints/isissue/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

Як вже було 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)
    ))
) || ''

25

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

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

Функція toString () URLSearchParams перетворить аргументи запиту в рядок, який можна додати до URL-адреси. У цьому прикладі toString () викликається неявно, коли він об'єднується з URL-адресою.

IE не підтримує URLSearchParams, але є поліфіли .

Якщо ви використовуєте вузол, ви можете знайти URLSearchParams як глобальний об’єкт з версії 10. У більш старій версії ви можете знайти його require('url').URLSearchParamsнатомість. Фактичний API вибору не є частиною вузла, і його потрібно додати через пакет, як -от вилучення вузлів .



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

7
Варто визначити, що це надійно працює лише з цілими типами. Якщо ви використовуєте рядки, особливо надані користувачем (наприклад , ті , критерії пошуку) , то ви повинні бігти рядки, в іншому випадку ви можете отримати дивні результати , якщо символи подобається /, +або &з'явитися в рядку.
Malvineous

Використання об'єкта Request може допомогти, особливо якщо ви хочете скористатися функцією для складання запиту, а потім передати це виклику fetch (), але я не думаю, що його використання "абсолютно очевидно". Також URL не повинен бути вказаний в об'єктному літералі параметрів конфігурації; він повинен бути переданий окремо як 1-й параметр конструктору запиту ( developer.mozilla.org/en-US/docs/Web/API/Request/Request ).
Ген1-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
Ви повинні бути дуже обережними з цим методом, оскільки він не спочатку запускає URL-адрес у рядки. Тож якщо ви отримаєте змінну, яка містить такий собі символ, +або &він не працюватиме так, як очікувалося, і ви отримаєте різні параметри та значення для того, що ви думали.
Malvineous

-1

Якраз працював з fetchesModule 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.