使用Fetch GET请求设置查询字符串


147

我正在尝试使用新的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

Answers:


173

2017年3月更新:

URL.searchParams支持已正式登陆Chrome 51,但其他浏览器仍然需要polyfill


使用查询参数的官方方法是将其添加到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是否支持searchParamsURL 的属性(在撰写本文时),因此您可能要使用第三方库自备解决方案

2018年4月更新:

随着使用 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)

旁注: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=urlsearchparamsURLSearchParams。我会假设(尽管我不是100%肯定)红色的浏览器确实是URL对象没有.searchParams属性的浏览器。重要的是,Edge仍然没有支持。
Mark Amery

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

1
它确实是错误添加的:) 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

正如已经回答的,按照规范,这是不可能的 fetch -API尚。但我要注意:

如果打开node,则有querystring包装。它可以对对象/查询字符串进行字符串化/解析:

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

...然后将其附加到要请求的网址。


但是,上述问题是,您总是必须在前面加上一个问号(?)。因此,另一种方法是使用parsenodes 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)
    ))
) || ''

24

简洁的ES6方法:

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

URLSearchParam的 toString()函数会将查询args转换为可以附加到URL的字符串。在此示例中,当toString()与URL串联时,将隐式调用它。

IE不支持此功能,但是有可用的polyfill


9

您可以使用#stringify查询字符串

import { stringify } from 'query-string';

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

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 —将对象编码为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"

5

我知道这说明绝对显而易见,但是我觉得值得一提,因为这是最简单的方法:

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

7
值得一提的是,它只能可靠地与整数类型一起使用。如果使用字符串,尤其是用户提供者(如搜索条件),那么你必须转义字符串,否则你可以得到奇怪的结果,如果喜欢的字符/+&出现的字符串中。
Malvineous

使用Request对象可以有所帮助,特别是如果您想使用一个函数来构建请求,然后将其交给fetch()调用时,尤其如此,但我认为使用它不是“绝对显而易见的”。另外,不应在config选项的对象文字中指定url;它应该作为第一个参数分别传递给Request构造函数(developer.mozilla.org/en-US/docs/Web/API/Request/Request)。
代Gen

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

只是与Nativescript的fetchModule一起工作,并使用字符串操作找出了自己的解决方案。将查询字符串一点一点地追加到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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.