最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Use fetch to send get request with data object - Stack Overflow

programmeradmin1浏览0评论

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
Add a comment  | 

3 Answers 3

Reset to default 12

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'

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.

发布评论

评论列表(0)

  1. 暂无评论