Reputation: 45
An ajax function from jQuery
$.ajax({
method: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
})
.done(function( msg ) {
console.log( "Data Saved: " + msg );
});
And this is a request using a fetch API
const data = { name: "John", data: "Boston" };
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: data,
};
const response = await fetch('/api ',options);
const responseData = await response.json();
console.log(responseData);
Also how come this fetch implementation is producing an error in my node terminal ?
If I use a digit instead of 'Boston' for example the Unexpected token changes to '<' .
SyntaxError: Unexpected token o in JSON at position 1
at JSON.parse (<anonymous>)
Is there anything I should watch out for between these two?
data of ajax and body of fetch?
(I am not using them simultaneously the way)
Upvotes: 3
Views: 2745
Reputation: 1075029
From the documentation we can see that...
When data is an object, jQuery generates the data string from the object's key/value pairs unless the
processData
option is set to false. For example,{ a: "bc", d: "e,f" }
is converted to the string"a=bc&d=e%2Cf"
. If the value is an array, jQuery serializes multiple values with same key based on the value of the traditional setting (described below). For example,{ a: [1,2] }
becomes the string"a%5B%5D=1&a%5B%5D=2"
with the defaulttraditional: false
setting.
fetch
doesn't do that. But separately, you've said you're sending JSON by including Content-Type: application/json
as a header, but you aren't doing that (and your jQuery code doesn't do that either, it sends URI-encoded data).
You have to do it yourself. If you want to send JSON, use JSON.stringify
:
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
};
If you want to send URI-encoded data, use URLSearchParams
:
const data = new URLSearchParams([ // Note this is an array of
["name", "John"], // [name, value] arrays
["data", "Boston"],
]);
const options = {
method: 'POST',
body: data,
};
If you want to send standard form encoding, use FormData
(exactly like the above, but with FormData
instead of URLSearchParams
.
Also how come this fetch implementation is producing an error in my node terminal ? If I use a digit instead of 'Boston' for example the Unexpected token changes to '<' .
SyntaxError: Unexpected token o in JSON at position 1 at JSON.parse (<anonymous>)
Because your object is being coerced to a string, and it coerces to "[object Object]"
, which is invalid JSON as of the o
.
Side note: Your fetch
code is falling prey to a footgun in the API: fetch
only rejects its promise on network error, not on HTTP error. You can't assume that a fulfilled promise from fetch
means your request was successful, you have to check:
const response = await fetch('/api ',options);
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
const responseData = await response.json();
console.log(responseData);
Upvotes: 4
Reputation: 944010
'Content-Type': 'application/json',
You claim you are sending JSON.
const data = { name: "John", data: "Boston" }; body: data,
data
is an object, not JSON.
When it gets forced into a string (because it isn't a data type recognised by fetch
so it gets converted to a string automatically) it becomes "[object Object]"
which is still not JSON. (The [
starts an array and then the o
is an error).
If you want to send JSON, you need to convert to the object to JSON yourself. Use JSON.stringify
.
Also note that while the server-side code appears to be able to handle JSON input, jQuery sends application/x-www-form-urlencoded
data, not JSON.
So to match that you would need:
var searchParams = new URLSearchParams();
searchParams.append("name", "John");
searchParams.append("location", "Boston");
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: searchParams.toString(),
};
const response = await fetch('/api ',options);
const responseData = await response.json();
console.log(responseData);
Upvotes: 3