I'm using Fetch (Fetch API) in a project and I would like to, for consistence purposes, create a function that receives all the parameters such as method, url and data and creates the correct request, depending if it's a GET or a POST request.
Is it possible, using Fetch, to send a data object that for the GET request, converts data into and string with the parameters and if it is a POST request, it just sends the data object in the body?
It would look like this:
fetch ('/test', {
method: 'GET',
data: {
test: 'test'
}
});
This doubt was inspired by this jQuery ajax behaviour:
$.ajax({
url: '/test',
method: 'GET',
data: {
test: 'test'
}
});
This would produce this request:
'/test/?test=test'
I'm using Fetch (Fetch API) in a project and I would like to, for consistence purposes, create a function that receives all the parameters such as method, url and data and creates the correct request, depending if it's a GET or a POST request.
Is it possible, using Fetch, to send a data object that for the GET request, converts data into and string with the parameters and if it is a POST request, it just sends the data object in the body?
It would look like this:
fetch ('/test', {
method: 'GET',
data: {
test: 'test'
}
});
This doubt was inspired by this jQuery ajax behaviour:
$.ajax({
url: '/test',
method: 'GET',
data: {
test: 'test'
}
});
This would produce this request:
'/test/?test=test'
Share
Improve this question
edited Aug 31, 2016 at 12:35
Bergi
665k161 gold badges1k silver badges1.5k bronze badges
asked Aug 31, 2016 at 9:38
Defesa EsquerdoDefesa Esquerdo
3202 gold badges3 silver badges10 bronze badges
4
- 1 Well, yes, this is possible. But what is your question exactly? (note: you are aware of the fact that IE and safari don't support this?) – giorgio Commented Aug 31, 2016 at 9:40
- Yes, I'm aware of that, it's just for an experiment :) My question is: If I pass the data object as normal in the fetch constructor for a GET request, would it send the request like the example I gave '/test/?test=test' ? – Defesa Esquerdo Commented Aug 31, 2016 at 12:12
- 3 Did you try it ? – Royi Namir Commented Aug 31, 2016 at 12:21
- I tried it but I was more interested in the iteration through the multiple properties in the data object. Besides I searched for this question here and I couldn't find nothing, so I decided to create a topic that might be useful to other developers. Thank you! :) – Defesa Esquerdo Commented Aug 31, 2016 at 14:10
3 Answers
Reset to default 12If I pass the data object as normal in the fetch constructor for a GET request, would it send the request like the example I gave '/test/?test=test'
If you want to add query string to a fetch request :
From the SPEC
var url = new URL("https://a.com/method"),
params = {a:1, b:2}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
fetch(url)
this will produce a request :
you could either use the Url class:
var url = new URL("/test/")
Object.keys({test: 'test', a: 1}).forEach(key => url.searchParams.append(key, params[key]))
fetch(url);
or parse the string yourself, if you want wider browser support:
var params = {test: 'test', a: 1},
qs = Object.keys(params).reduce(function(_qs, k, i){ return _qs + '&' + k + '=' + params[k]; }, '').substring(1);
console.log(qs)
I'll show you snippets for creating query with and without using URLSearchParams
.
The code will be in typescript for the if you're using it. if not, just remove types, it will work in the same way.
Simple solution (URLSearchParams)
/**
* Creates query from given object
* - It doesn't work with deep nesting
* - It doesn't remove empty fields
* @returns `state1=6&state2=horse` without `?`
*/
function createQuery(queryObject?: Record<string | number, unknown> | null): string {
if (queryObject == null) return ""
// Typescript: The `as ...` expression here is ok because `URLSearchParams` will convert non-string by itself
const searchParams = new URLSearchParams(queryObject as Record<string, string>)
return searchParams.toString()
}
Solving problems solution (URLSearchParams)
/**
* Creates query from given object
* - It doesn't work with deep nesting
* - Removes empty fields
* @returns `state1=6&state2=horse` without `?`
*/
function createQuery(queryObject?: Record<string | number, unknown> | null): string {
if (queryObject == null || !Object.keys(queryObject).length) return ""
for (const key in queryObject) {
if (Object.prototype.hasOwnProperty.call(queryObject, key)) {
const value = queryObject[key]
// Use `!value` expression if you want to delete values as `0` (zero) and `""` (empty string) too.
if (value == null) delete queryObject[key]
}
}
const searchParams = new URLSearchParams(queryObject as Record<string, string>)
return searchParams.toString()
}
No URLSearchParams solution
/**
* Creates query from given object
* - Supports prefixes
* - Supports deep nesting
* - Removes empty fields
* @returns `state1=6&state2=horse` without `?`
*/
function createQuery(queryObject?: Record<string | number, unknown> | null, keyPrefix?: string): string {
if (queryObject == null || !Object.keys(queryObject).length) return ""
keyPrefix = keyPrefix ? (keyPrefix + "_") : ""
const queryKeys = Object.keys(queryObject)
const queryArray = queryKeys.map(key => {
const value = queryObject[key]
if (value) {
if (isDictionary(value)) {
return createQuery(value, keyPrefix + key + "_")
}
return keyPrefix + encodeURIComponent(key) + "=" + encodeURIComponent(String(value))
}
return ""
})
return queryArray.filter(Boolean).join("&")
}
isDictionary Helper
I used isDictionary
helper here too, you can find it here
Usage
You need to put ?
in the beginning of your endpoint plus createQuery
fetch("/test?" + createQuery({ foo: 12, bar: "@user->here", object: { test: "test", bird: { super: { ultra: { mega: { deep: "human" }, shop: 7 } }, multiple: [1, 2, 3] } } }))
Result
foo=12&bar=%40user-%3Ehere&object_test=test&object_bird_super_ultra_mega_deep=human&object_bird_super_ultra_shop=7&object_bird_multiple=1%2C2%2C3
or
foo: 12
bar: @user->here
object_test: test
object_bird_super_ultra_mega_deep: human
object_bird_super_ultra_shop: 7
object_bird_multiple: 1,2,3
Conclusion
We got different snippets you can choose from depending on your goals.