I'm trying to use the newFetch API:
I am making aGET request like this:
var request = new Request({ url: 'http://myapi.com/orders', method: 'GET'});fetch(request);However, I'm unsure how to add a query string to theGET request. Ideally, I want to be able to make aGET request to aURL like:
'http://myapi.com/orders?order_id=1'InjQuery I could do this by passing{order_id: 1} as thedata parameter of$.ajax(). Is there an equivalent way to do that with the newFetch API?
14 Answers14
A concise, modern approach:
fetch('https://example.com?' + new URLSearchParams({ foo: 'value', bar: 2,}).toString())How it works:URLSearchParams toString() method will convert the URLSearchParams instance into a string representation, which happens to be a properly encoded query string.
It is also legal to leave out the.toString() call like so:fetch('https://...' + new URLSearchParams(...)). JavaScript automatically calls.toString() when an object is concatenated with a string. This does require future code readers to have a deeper understanding of the language to understand your code.
A complete example of a fetch request with query parameters:
// Real example you can copy-paste and play with.// jsonplaceholder.typicode.com provides a dummy rest-api// for this sort of purpose.async function doAsyncTask() { const url = ( 'https://jsonplaceholder.typicode.com/comments?' + new URLSearchParams({ postId: 1 }).toString() ); const result = await fetch(url) .then(response => response.json()); console.log('Fetched from: ' + url); console.log(result);}doAsyncTask();If you are using/supporting...
IE: Internet Explorer does not provide native support for URLSearchParams or fetch, but there arepolyfillsavailable.
Node: As of Node 18 there is native support for the fetch API (in version 17.5 it was behind the
--experimental-fetchflag). In older versions, you can add the fetch API through a package likenode-fetch. URLSearchParams comes with Node, and can be found as a global object since version 10. In older version you can find it atrequire('url').URLSearchParams.TypeScript: The values provided to
URLSearchParamswill be auto-coerced into a string, which is why TypeScript's definition forURLSearchParamsrequires you to provide all values as strings. Those who don't use TypeScript may be comfortable providing other value types to this function if they feel the coercion behavior is intuitive. For examples, numbers will behave exactly as you would expect, while the way arrays get implicitly coerced may cause confusion to future readers.TypeScript v4 or older with Node: Older versions of TypeScript did not offer type definitions for the global URLSearchParams in the Node environment. The simplest workaround is to just import it from the
urlmodule. This later got resolved at some point during v4 (I'm not sure what the exact version is that fixes this). Seethis issue for more info.
9 Comments
new URLSearchParams({foo: ['bar', 'baz']}) but rather thanfoo=bar&foo=baz it gets escaped asfoo=bar%Cbazs = new URLSearchParams({foo: 'bar'}); s.append('foo', 'baz'); s.toString(). Alternativly, the constructor can take a list of lists instead of an object.new URLSearchParams([['foo', 'bar'], ['foo', 'baz']]).toString() See the docs page for more usage info:developer.mozilla.org/en-US/docs/Web/API/URLSearchParamshttps://example.com?${new URLSearchParams({foo: 'value'})} ```developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…bar: 2 should bebar: '2'.Update March 2017:
URL.searchParams support has officially landed in Chrome 51, but other browsers still require apolyfill.
Theofficial way to work with query parameters is just to add them onto the URL. Fromthe spec, this is an example:
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(/* … */)However, I'm not sure Chrome supports thesearchParams property of a URL (at the time of writing) so you might want to either use athird party library orroll-your-own solution.
Update April 2018:
With the use ofURLSearchParams constructor you could assign a 2D array or a object and just assign that to theurl.search instead of looping over all keys and append them
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 is also available in NodeJS
const { URL, URLSearchParams } = require('url');13 Comments
URLSearchParams interface; I wouldassume (though I'm not 100% certain) that the browsers in red there are exactly the browsers for whichURL objects will not have the.searchParams property. Importantly, Edge still does not have support.new URLSearchParams doesn't seem to work correctly withArray properties. I expected it to convert the propertyarray: [1, 2] toarray[]=1&array[]=2, but converted it toarray=1,2. Manually using theappend method of it does result inarray=1&array=2, but I would have to iterate over params object, and do that only for array types, not very ergonomic.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) });4 Comments
?, there's two allowed ways to encode a space, both%20 and+ are acceptable. So while bothURLSearchParams() andencodeURIComponent() will give out different results, a server is supposed to be able to accept either.As already answered, this is per spec not possible with thefetch-API, yet. But I have to note:
If you are onnode, there's thequerystring package. It can stringify/parse objects/querystrings:
var querystring = require('querystring')var data = { key: 'value' }querystring.stringify(data) // => 'key=value'...then just append it to the url to request.
However, the problem with the above is, that you always have to prepend a question mark (?). So, another way is to use theparse method from nodesurl package and do it as follows:
var url = require('url')var data = { key: 'value' }url.format({ query: data }) // => '?key=value'Seequery athttps://nodejs.org/api/url.html#url_url_format_urlobj
This is possible, as it does internally justthis:
search = obj.search || ( obj.query && ('?' + ( typeof(obj.query) === 'object' ? querystring.stringify(obj.query) : String(obj.query) ))) || ''Comments
You can set params on yourURL'ssearchParams:
const url = new URL('http://myapi.com/orders');url.searchParams.set('order_id', '1');fetch(url);This has the advantage of building a request explicitly while allowing the originalURL to be in any valid format.
4 Comments
fetch withconsole.log. It logs the original URL from line one without the query string you attempt to add on line two when I test in Firefox, Safari, or Chrome.${process.env.API_URL}/messages?${searchParams.toString()}); fetch(url);You can usestringify fromquery-string.
import { stringify } from 'query-string';fetch(`https://example.org?${stringify(params)}`)Comments
encodeQueryString — encode an object as querystring parameters
/** * 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"Comments
I know this is stating the absolute obvious, but I feel it's worth adding this as an answer as it's the simplest of all:
const orderId = 1;fetch('http://myapi.com/orders?order_id=' + orderId);3 Comments
/,+ or& appear in the string.Solution without external packages
to perform aGET request using the fetch api I worked on this solution that doesn't require the installation of packages.
this is an example of a call to the google's map api
// encode to scape spacesconst 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 stringconst query = Object.keys(params).map(k => `${esc(k)}=${esc(params[k])}`).join('&')const res = await fetch(url+query);const googleResponse = await res.json()feel free to copy this code and paste it on the console to see how it works!!
the generated url is something like:
https://maps.googleapis.com/maps/api/geocode/json?key=asdkf%C3%B1laskdGE&address=evergreen%20avenue&city=New%20Yorkthis is what I was looking before I decided to write this, enjoy :D
3 Comments
const esc = encodeURIComponent except making the code harder to read?I like to use the URL API in such cases
const url = new URL('http://myapi.com/orders');url.searchParams.append('sort', 'date');url.searchParams.append('order', 'desc');fetch(url.href);Comments
Maybe this is better:
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);});Comments
Template literals are also a valid option here, and provide a few benefits.
You can include raw strings, numbers, boolean values, etc:
let request = new Request(`https://example.com/?name=${'Patrick'}&number=${1}`);You can include variables:
let request = new Request(`https://example.com/?name=${nameParam}`);You can include logic and functions:
let request = new Request(`https://example.com/?name=${nameParam !== undefined ? nameParam : getDefaultName() }`);As far as structuring the data of a larger query string, I like using an array concatenated to a string. I find it easier to understand than some of the other methods:
let queryString = [ `param1=${getParam(1)}`, `param2=${getParam(2)}`, `param3=${getParam(3)}`,].join('&');let request = new Request(`https://example.com/?${queryString}`, { method: 'GET'});1 Comment
+ or& then it won't work as expected and you'll end up with different parameters and values to what you thought.const query = { is_active: true,};let url = `${apiUrl}/<endPoint>`;const searchParams = Object.keys(query).length ? new URLSearchParams(query).toString() : null;if (searchParams) {url = `${url}?${searchParams}`}for nextJs 13+
const response = await fetch(url, { method: "GET", next: { // revalidate will be after 4 min revalidate: 240, }, // cache: "no-cache",});Comments
Was just working with Nativescript's fetchModule and figured out my own solution using string manipulation.Append the query string bit by bit to the url. Here is an example where query is passed as a json object (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.}I tested this over a multiple number of query parameters and it worked like a charm :)Hope this helps someone.
3 Comments
Explore related questions
See similar questions with these tags.











