I'm using javascript and calling an API which returns some JSON. For some reason, when I assign the JSON to a variable, it removes some of the data. If I console log the variable (in this case data2) it is not the same output as when I just put a function JSON.parse(data) inside the console log.
let data = await res.text();
console.log("data1: ",JSON.parse(data))
const data2 = JSON.parse(data);
console.log("data2: ",data2);
Both console logs should be the same but they are not.
I've tried everything to figure this out but in the end my understanding is the console should be printing the exact same thing
All of this code is in a function so it shouldn't be reused or mutated (that I'm aware of). The full function is here (cleaned up and using res.josn())
const post = async (url, params) => {
const res = await fetch(BASE_URL + url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(params),
});
const data = await res.json();
console.log("data1: ",data)
return data1;
};
In this case, the data variable is incomplete and not showing the full response
Related
I am running 3 API requests and they are making my JS script very slow.
The goal is to fetch data from the API and push it my database.
First 2 API is called using date and next_page_token. So until there is a next page token i keep calling these 2 APIs. I call them recursively.
I store the id that i get from above in an array and pass it to the next 2 APIs.
The last API call run in a loop. I loop through the ids and call the API each time.
Code:
export async function getFirstAPI(access_token, start, end, globalObject){
let url = 'baseAPI/meetings/from=start/to=end/next_page_token=globalObject.next_page_token';
var obj = {
method: 'GET',
headers: {
authorization: 'Bearer {yourtokenhere}'
}
}
let response = await fetch(url, obj)
let data = await response.json()
return data
}
export async function getSecondAPI(access_token, start, end, globalObject){
let url = 'baseAPI/chats/from=start/to=end/next_page_token=globalObject.next_page_token';
var obj = {
method: 'GET',
headers: {
authorization: 'Bearer {yourtokenhere}'
}
}
let response = await fetch(url, obj)
let data = await response.json()
return data
}
export async function getThirdAPI(access_token, id_array, globalObject){
for(let i=0; i<id_array.length; i++){
let url = 'baseAPI/participants/{id}';
var obj = {
method: 'GET',
headers: {
authorization: 'Bearer {yourtokenhere}'
}
}
let response = await fetch(url, obj)
let data = await response.json()
globalObject.store_data.push(data)
}
return globalObject
}
When i run the above for a single day. That alone takes 14min 20sec. If i run it for a wider date range i am guessing this will go on for hours!!
Is there a way i can optimize this code? Or is it supposed to take this much time to run?
Any suggestions would be great!!
Switch from await in your loop to Promise.all or Promise.allSettled. It will work much faster. Await is not a silver bullet. It helps but in your case you are waiting for a response on each iteration instead of.. something like "fire all and collect results"
export async function getThirdAPI(access_token, id_array, globalObject) {
const apiPromises = id_array.map(async (id) => {
let url = `${baseAPI}/participants/${id}`;
var obj = {
method: 'GET',
headers: { /* */ },
authorization: `Bearer ${access_token}`
}
const response = await fetch(url, obj);
return await response.json();
});
const results = await Promise.all(apiPromises);
// in case globalObject.store_data is an array
globalObject.store_data.push(...results);
return globalObject;
}
I'm relatively new when it comes to Typescript/Javascript, but I'm trying to set all indices of this.articles[i].result within setBias() equal to setBiasedRating(this.articles[i].url);, the function containing the API call. So far I have this:
async getBiasedRating(url) {
const response = await fetch(
'https://news-bias-detection-api.herokuapp.com/',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: `{
"url": "${url}"
}`,
}
);
const data = await response.json();
return data;
}
async setBias() {
for (let i = 0; i < this.articles.length; ++i) {
try {
this.articles[i].result = await this.getBiasedRating(
this.articles[i].url
);
} catch (e) {
throw new Error("Error fetching bias news data");
}
}
}
}
Here, when I loop through all the indices in the this.articles array and set the i'th index equal to the response I get from getBiasedRating(this.articles[i].url), I see many repeating POST 500 (INTERNAL SERVER ERROR)'s.
I have no idea why this is, since if I have the same functionality, just with the first index instead of looping through everything:
async setBias() {
this.articles[0].result = await this.getBiasedRating(this.articles[0].url)
}
This works just fine, and the data for this.articles[0] gets stored correctly. If anyone could explain why the for loop doesn't work here, it would be greatly appreciated.
HTTP ERROR 500 isn't problem in your code, it's a server problem.
I'm trying to access the returned content-type from my GET request so I can decide the kind of preview I want to like for html maybe pass through an iframe and for a PDF maybe some viewer. The problem is when I do console.log(response.headers) the object returned doesn't have content-type in it but when I check the networks tab the response headers has content-type:html/text. How can I get the content-type from the response headers?
this is how my GET request looks like
const getFile = async () => {
var requestOptions = {
method: "GET",
headers: context.client_header,
redirect: "follow",
};
let statusID = context.currentStatus.ApplicationID;
var response = await fetch(
process.env.REACT_APP_API_ENDPOINT +
"/services/getStatus?ApplicationID=" +
statusID,
requestOptions
);
console.log(response.headers);
if (response.ok) {
let fileHtml = await response.text();
setfileURL(fileHtml);
} else {
alert.show("Someting went wrong");
}
};
The Headers object isn't a great candidate for console.log() since it is not easily serialisable.
If you want to see everything in it, try breaking it down to its entries via spread syntax
console.log(...response.headers)
You'll probably find that you can in fact access what you want via
response.headers.get("content-type")
See Headers.get()
I'm trying to fetch() text/plain data from a remote service. If I place a breakpoint in the promise "then" chain, the text data from the server is available. Without the breakpoint, I get a fetch() exception.
I am using a prototype design pattern (see below). When I place a breakpoint in the "then" chain as shown below, the data from the remote service is successfully retrieved. Without the breakpoint, the catch() is executed and the error is:
TypeError: Failed to fetch
I'm totally stumped and would appreciate any help!
Note, the server (a python app) sends back html, with
self.send_header("Access-Control-Allow-Origin", "*")
Also, if I use Ajax (FWIW, it works). I'd like to get it working with fetch() however.
function Fetch(Msg) {
// Msg contains some info on how to construct the JSON message to transmit -- not relevant here.
this.help = `
The Fetch object specifies communication basics using
the fetch(...) mechanism.
`;
// some misc object vars...
}
Fetch.prototype = {
constructor: Fetch,
postData: async function (url = '', data = {}) {
const response = await fetch(url, {
method: 'POST,
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'text/plain',
},
redirect: 'follow',
referrerPolicy: 'no-referrer',
// body data type must match "Content-Type" header
body: JSON.stringify(data)
});
return await response.text(); //
},
handleErrorsInResponse: function (response) {
var debug = new Debug("Fetch.handleErrorsInResponse");
debug.entering();
debug.leaving();
},
handleReponse: function (response) {
var debug = new Debug("Fetch.handleResponse");
debug.entering();
console.log(response);
debug.leaving();
},
handleErrorsInFetch: function (response) {
var debug = new Debug("Fetch.handleErrorsInFetch");
debug.entering();
console.log(response);
debug.leaving();
},
call: function (payload) {
this.postData(
'http://some.url/',
payload)
.then(this.handleErrorsInResponse) // If I place a breakpoint here it works!
.then(this.handleReponse)
.catch(this.handleErrorsInFetch);
},
}
// Ultimately called by something like
comms = new Fetch();
someData = {"key": someJSON};
comms.call(someData);
Remove the wait on the response.
Replace
return await response.text();
by
return response.text();
I am trying to put fetch functions into a separated file, so I can organise these API fetch easily. However, when I try to fetch and return the data, it gives me null or an unexpected json object. Here is part of my src:
//api.js
export async function LoginAPI(username, password) {
const url = baseURL + "/login/";
var params = {username: username, password: md5.hex_md5(password)};
let response = await fetch(url, {
method: 'POST',
headers: {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'},
body: JSON.stringify(params)
});
return await fetch(url, {
method: 'POST',
headers: header,
body: JSON.stringify(params)
})
.then((res) => res.text())
.then((text) => text.length ? JSON.parse(text) : {})
.catch((error) => {
throw error;
});
};
Here is the another file.
//index.js
var Login = React.createClass({
onPress_login: function() {
var value = this.refs.form.getValue();
if (value) {
result = LoginAPI(value.username, value.password);
console.log(result);
} else {
this.AlertDialog.openDialog();
}
},
render() {
return (
(...)
<Button onPress={this.onPress_login}>
<Text>Login</Text>
</Button>
The fetch is working, it is communicating with the server. However, the console log returns me this at the first place
Promise _45: 0_54: null _65: null _81: 1 __proto__: Object
I am assuming that the result log in the console at the first place is not the await result (the actual response from server, but an object of fetch response). I tried to search out methods online but I can't find any post/blog/article saying how to do fetch as a function call.
Is there any way to do like swift, LoginAPI(username, password, callback: {...}) please?
The problem is that you're are making an async function and not waiting for the response, the you see that kind of console log.
Try this:
result = await LoginAPI(value.username, value.password);
Let me know if this was your problem.