6

I recently found myself converting a function that calls a remote API, from returning a callback to returning a Promise. I thought that'd be a great opportunity to also replace the $.ajax call with a fetch call, as fetch already returns a Promise.

However, this specific call is a GET that actually expects a payload (containing key and return type). Specifically, I call it using:

$.ajax({
    type: 'GET',
    contentType: 'application/json; charset=utf-8',
    url: config.serviceUrl,
    data: {
        apiKey: key,
        format: 'json'
    }
})
.done(data => {...})
.fail((jqXHR, textStatus, errorThrown) => {...});

However, fetch does not have a data property, and it throws an error if you try to send a body with a GET request (TypeError: Failed to execute 'fetch': Request with GET/HEAD method cannot have body). And according to the Chromium forums this is the expected behavior.

Bear in mind: I have absolutely no control of the external API, so mentioning that sending a payload with GET violates some API protocol, or suggesting I change the underlying call, is not helpful.

Is it possible to use fetch in this scenario? How?

1
  • You can use the body property of a fetch request to add data, such as a FormData object to the request. Also note that Fetch is highly experimental at this stage and not well supported. I'd personally stick with AJAX for now. It would also be helpful if you showed us the actual Fetch request you've written Commented Nov 2, 2016 at 17:39

2 Answers 2

8

jQuery's ajax function simply appends data to the URL as URL parameters for GET requests:

data

Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests.

Source


Using fetch, you can either do it manually, or you could use an approach similar to that:

var url = new URL("http://youapi.com")
var data = {
    apiKey: key,
    format: 'json'
}

Object.keys(data).forEach(key => url.searchParams.append(key, data[key]))
fetch(url)
Sign up to request clarification or add additional context in comments.

2 Comments

Wasn't aware that all it did was concatenate url params! Great find! Thanks!
FYI, that method above (url.searchParams.append) won't handle nested objects or arrays correctly.
6
   var headers = new Headers();
   headers.append("Content-Type", "application/json; charset=utf-8");
   fetch(config.serviceUrl + "?apiKey=" + key + "&format=json", 
     {headers:headers, method:"GET"}
   ).then(response => response.json())
   .then(json => /* do stuff with `json` */)
   .catch(err => console.error(err));

is equivalent to current $.ajax() call.

5 Comments

Thanks! that's what I was looking for. Wish I could mark both yours and TimoSata's as the right answers.
Looks like I'll have to abandon this attempt. I keep getting Unexpected token j in JSON at position 0 on the response.json() operation. Since $.ajax returns perfectly formed json, I'll just drop fetch. :(
@TravelingTechGuy What is the response? Can you reproduce syntax error at jsfiddle jsfiddle.net or plnkr plnkr.co? Have you tried using response => response.text() then .then(text => {json = JSON.parse(text)} within chained .then()?
Thanks for the offer, but no need - I think I solved it: probably me testing so many times caused a 500 error on the server - that still returned a response with the ok property set to true - so it didn't reject on the fetching, but obviously rejected on the json parsing. While I got that eventually, it still makes me suspect that fetch is still not ready for production.
@TravelingTechGuy See documentation developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch "A fetch() promise rejects with a TypeError when a network error is encountered, although this usually means a permissions issue or similar. An accurate check for a successful fetch() would include checking that the promise resolved, then checking that the Response.ok property has a value of true. An HTTP status of 404 does not constitute a network error.". You should be able to test at either of editors by supplying the JSON at data {json:JSON.stringify(json)} or .json file at plnkr

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.