Đặt chuỗi truy vấn bằng yêu cầu Fetch GET


147

Tôi đang cố gắng sử dụng API tìm nạp mới :

Tôi đang thực hiện một GETyêu cầu như thế này:

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

Tuy nhiên, tôi không chắc cách thêm chuỗi truy vấn vào GETyêu cầu. Lý tưởng nhất, tôi muốn có thể đưa ra GETyêu cầu URLnhư sau:

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

Trong jQuerytôi có thể làm điều này bằng cách chuyển {order_id: 1}như datatham số của $.ajax(). Có một cách tương đương để làm điều đó với cái mới Fetch API?

Câu trả lời:


173

Cập nhật tháng 3 năm 2017:

Hỗ trợ URL.searchParams đã chính thức cập bến Chrome 51, nhưng các trình duyệt khác vẫn yêu cầu một polyfill .


Cách chính thức để làm việc với các tham số truy vấn chỉ là thêm chúng vào URL. Từ thông số kỹ thuật , đây là một ví dụ:

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

Tuy nhiên, tôi không chắc Chrome hỗ trợ thuộc searchParamstính của URL (tại thời điểm viết bài) nên bạn có thể muốn sử dụng thư viện của bên thứ ba hoặc giải pháp của riêng bạn .

Cập nhật tháng 4 năm 2018:

Với việc sử dụng hàm tạo URLSearchParams, bạn có thể gán một mảng 2D hoặc một đối tượng và chỉ cần gán nó cho url.searchthay vì lặp qua tất cả các khóa và nối thêm chúng

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: URLSearchParamscũng có sẵn trong NodeJS

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

1
Ngoài ra còn có developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/ Lời , khi viết bài này, nó vẫn tiếp tục thông qua thông số kỹ thuật và chưa được hỗ trợ tốt. Và API giống với Java hơn là JS. : /
ericsoco

1
Xem caniuse.com/#feat=urlsearchparams để được hỗ trợ cho URLSearchParamsgiao diện; Tôi sẽ giả định (mặc dù tôi không chắc chắn 100%) rằng các trình duyệt màu đỏ có chính xác các trình duyệt mà URLcác đối tượng sẽ không có thuộc .searchParamstính. Điều quan trọng, Edge vẫn không có hỗ trợ.
Mark Amery

1
Từ tài liệu: "Lưu ý rằng việc sử dụng phiên bản URLSearchParams không được chấp nhận; các trình duyệt sẽ sớm sử dụng USVString cho init." nguồn: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/
mẹo

1
new URLSearchParamsdường như không hoạt động chính xác với Arraycác thuộc tính. Tôi dự kiến ​​nó sẽ chuyển đổi tài sản array: [1, 2]sang array[]=1&array[]=2, nhưng chuyển đổi nó thành array=1,2. Sử dụng thủ công appendphương thức của nó sẽ dẫn đến kết quả array=1&array=2, nhưng tôi sẽ phải lặp lại đối tượng params và chỉ làm điều đó cho các kiểu mảng, không thuận tiện cho lắm.
xóa sổ

1
Nó thực sự đã được thêm vào lỗi :) 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)
  });

26

Như đã trả lời, điều này là không thể với thông số kỹ thuật với fetch-API. Nhưng tôi phải lưu ý:

Nếu bạn đang trên node, có querystringgói. Nó có thể xâu chuỗi / phân tích các đối tượng / truy vấn:

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

... sau đó chỉ cần thêm nó vào url để yêu cầu.


Tuy nhiên, vấn đề ở trên là, bạn luôn phải đặt trước một dấu hỏi ( ?). Vì vậy, một cách khác là sử dụng parsephương thức từ urlgói nút và thực hiện như sau:

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

Xem querytại https://nodejs.org/api/url.html#url_url_format_urlobj

Điều này là có thể, vì nó thực sự chỉ trong nội bộ này :

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

24

Một cách tiếp cận ES6 súc tích:

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

Hàm toString () của URLSearchParam sẽ chuyển đổi đối số truy vấn thành một chuỗi có thể được thêm vào URL. Trong ví dụ này, toString () được gọi ngầm khi nó được nối với URL.

IE không hỗ trợ tính năng này, nhưng có sẵn các polyfill .



5

Có lẽ điều này là tốt hơn:

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 - mã hóa một đối tượng dưới dạng tham số chuỗi truy vấn

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

Tôi biết điều này là rõ ràng tuyệt đối, nhưng tôi cảm thấy đáng để thêm nó như một câu trả lời vì nó đơn giản nhất trong tất cả:

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

7
Điều đáng giá là điều này chỉ hoạt động đáng tin cậy với các loại số nguyên. Nếu bạn sử dụng dây, đặc biệt là những người dùng cung cấp (như tiêu chí tìm kiếm) sau đó bạn phải thoát khỏi chuỗi, nếu không bạn có thể nhận được kết quả kỳ lạ nếu nhân vật thích /, +hoặc &xuất hiện trong chuỗi.
Malvineous

Sử dụng đối tượng Yêu cầu có thể giúp ích, đặc biệt nếu bạn muốn sử dụng một hàm để xây dựng yêu cầu và sau đó chuyển nó cho cuộc gọi tìm nạp (), nhưng tôi không nghĩ sử dụng nó là "rõ ràng tuyệt đối". Ngoài ra, url không nên được chỉ định trong đối tượng bằng chữ của các tùy chọn cấu hình; nó nên được truyền riêng như tham số thứ 1 cho hàm tạo yêu cầu ( developer.mozilla.org/en-US/docs/Web/API/Request/Request ).
Gen1-1

3

Mẫu chữ cũng là một lựa chọn hợp lệ ở đây, và cung cấp một vài lợi ích.

Bạn có thể bao gồm các chuỗi thô, số, giá trị boolean, v.v .:

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

Bạn có thể bao gồm các biến:

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

Bạn có thể bao gồm logic và chức năng:

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

Theo như cấu trúc dữ liệu của một chuỗi truy vấn lớn hơn, tôi thích sử dụng một mảng được nối với một chuỗi. Tôi thấy nó dễ hiểu hơn một số phương pháp khác:

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

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

8
Bạn phải rất cẩn thận với phương pháp này vì nó không thoát URL trước tiên. Vì vậy, nếu bạn nhận được một biến chứa một ký tự như +hoặc &sau đó nó sẽ không hoạt động như mong đợi và bạn sẽ kết thúc với các tham số và giá trị khác với những gì bạn nghĩ.
Malvineous

-1

Chỉ làm việc với fetchModule của Nigencript và tìm ra giải pháp của riêng tôi bằng cách sử dụng thao tác chuỗi. Nối chuỗi truy vấn từng bit vào url. Dưới đây là một ví dụ nơi truy vấn được truyền dưới dạng đối tượng 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.
}

Tôi đã thử nghiệm điều này qua nhiều số tham số truy vấn và nó hoạt động như một cơ duyên :) Hy vọng điều này sẽ giúp được ai đó.


1
Đây là một ví dụ tốt về lý do tại sao bạn nên sử dụng libs của bên thứ 3 - mã của bạn có thể hoạt động tốt, nhưng ai đó đã làm điều đó tốt hơn nhiều
refaelio

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.