How to slow down a single request / API endpoint for development? - javascript

EDIT: I am asking to slow down a SINGLE api call. Not the whole network. And I can't change the actual response time server side.
I am working in React. One component makes use of an API endpoint that sometimes takes very long. Every time that happens we allow the user to save, due to a bug.
I want to know how to slow down just that one API call, in order to create that particular situation.
So, I have for example
setLoading(true)
const templates = await getTemplates(dispatch)
setLoading(false)
in one component.
I would like to know what options I have to simulate that API response taking n seconds. No matter if doing that by code, tooling, etc..

setTimeout() on the server to delay sending the response, or on the client before resolving the promise.
EDIT: The code depends on your particular implementation/tools. Please share a snippet from your client-side function which calls the API, or the handler on the server.
Nevertheless, here's an example based on your snippet and JS's Promise/await combo:
setLoading(true)
const templates = await getTemplates(dispatch)
const delay = 1000;
await new Promise(resolve => setTimeout(resolve, delay));
setLoading(false);
Other example: node.js server
app.get('/api/whatever', (request, response) => {
const data = getDataFromDatabase():
const delay = 1000;
setTimeout(function() {
response.end(data);
}, delay);
})

Try this:
const call = (dati) => new Promise((resolve, reject) => {
setTimeout(() => { resolve(dati); }, 1000);
})
or you can see here: let promise wait a couple of seconds before return

Related

How to write requests and fetch

I need help how to correctly write a GET and POST request in my server (index.js) and how to properly write the fetch in App.js.
I have read threads here on Stackoverflow and I have searched for information on how to write requests and fetches but I find it very difficult how to add the examples to my own code. I have tried different solutions for three weeks but getting nowhere it feels like. So, please help. I feel like this should not be that difficult, but for some reason it is. I have no one to ask for help other than here.
I'm using the URL http://localhost:8080/reviews
Is this how I write or do I have to add anything? (in Index.js)
app.get("/reviews", (request, response) => {
response.status(201).json
});
app.post('/reviews', async (request, response) => {
response.status(201).json
});
In App.js I want to create a fetch where I GET all the existing reviews that are written (none at the moment since the page isn't done yet) and I want to be able to POST new reviews. When I post a new review I want the page to load and update with the new and all the other written reviews.
I have something like this at the moment, but I don't know what the last parts should be?
const reviewsURL = "http://localhost:8080/reviews"
export const App = () => {
const [existingReviews, setExistingReviews] = useState([])
const [newReview, setNewReview] = useState('')
const fetchReviews = () => {
fetch(reviewsURL, {'
// WHAT ELSE TO WRITE HERE ???
useEffect(() => {
fetchReviews();
}, []);
const postReview = (event) => {
event.preventDefault();
fetch(reviewsURL, {
method: 'POST',
// WHAT DO I WRITE HERE ???
}
return (
<>
<NewReview
newReview={newReview}
setNewReview={setNewReview}
handlesubmit={postReview}
/>
{<AllReviews
allReviews={existingReviews}
/>}
</>
)
}
In express.js, response.status(201).json is not the way to return a JSON response. .json is a function, so you would pass it a JSON-ifiable object, response.status(201).json(resultsArray); or something like that.
A lot of people prefer to use a library for making requests, rather than using fetch. Axios is a common favourite, and lots of people find it much easier to use.
If you'd prefer to use fetch over an easier library, that's fine, fetch is still simple enough to get going with. Here's some documentation on how to use fetch
Of note: the fetch(url) function returns a promise, so you'll either .then the returned promise, or await it inside an async function. If you're expecting a JSON response, the patterns in the example code in the docs require an extra step to get the content:
const result = await fetch(url);
const data = await result.json();
That's for a GET request, but the docs also show how to get going with POST requests.

React axios triggers bunch get requests

I have a server and a route('/is-working') in which I render simply Yes or No, in React I do a get request with Axios every second with the use of intervals to see if its working.
Here is the code:
useEffect(() => {
const interval = setInterval(async () => {
await axios.get('http://192.168.1.57/is-working')
.then(res => {
if (res?.status === 200) {
// Do somthing
}
})
.catch(err => {
return Promise.reject(err);
})
}, 1000);
return () => clearInterval(interval);
}, []);
I want to count the number of times I get a 200 response back, when I stop hosting http://192.168.1.57/is-working and it returns an network error, until now everything is fine, but when I start hosting http://192.168.1.57/is-working again it does a bunch of get requests all together. It seems its requesting all of the ones that returned network error again.
thanks for the help in advance.
That must be because you didn't defined a timeout for axios client. So, it still trying to request your endpoint, once it comes back it does all request at once
Take a look here: https://github.com/axios/axios#axioscreateconfig

Execute A Function When All xmlHttpRequests Are Complete

BRIEF
I have a website which gets data from an API. So it makes some post and get requests to a server once the website is opened. Let us assume it makes 5 different xmlHttpRequests as soon as the page loads but we cannot exactly know the time each call takes from start to finish.
FOR EXAMPLE
Call to one endpoint takes 2 seconds to complete and the other one takes 1 second to complete. So that means after 2 seconds both the calls are said to be finished.
TO-DO
I want to execute a function after all the xmlHttpRequests are complete because I am using window.performance.getEntries() to fetch all the requests initiated by the webpage and send it to my server as I am doing a web analytics project in which I need to access the times taken by each network request and convert the data into a chart.
EXTRA-QUESTION OR HINT
Is there any event that can be attached to the window as shown below to listen for all the network calls and execute my piece of code when all are finished.
window.addEventListener("load", function (event) {
//execute some code here
}
In the load event I am not able to capture all the requests by using performance.getEntries() because load fires before the ajax calls are finished.
As shown above I ask. Is there any trick or any event or anything in JavaScript by which we can wait untill all the XMLHTTPREQUESTS are finished and then execute some code.
WORKING SOLUTION
We can track browser AJAX calls using the code below :
const ajaxCallStatus = () => {
window.ajaxCalls = 0; // initial ajax calls
window.ajaxEndpoints = []; // keeping track of all ajax call urls (endpoints)
const origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
window.ajaxCalls++;
this.addEventListener('load', (event) => {
if (!window.ajaxEndpoints.includes(event['currentTarget'].responseURL)) {
window.ajaxEndpoints.push(event['currentTarget'].responseURL);
}
window.ajaxCalls--;
switch (window.ajaxCalls) {
case 0: // when ajax calls finish this runs
addData(window.ajaxEndpoints);
break;
}
});
origOpen.apply(this, arguments);
}
}
ADD DATA FUNCTION - Used for sending data to some backend.
function addData(arr, origOpen) {
XMLHttpRequest.prototype.open = origOpen;
axios.post('url', data)
.then((res) => console.log(res))
.catch((err) => console.log(err));
}
I would suggest you to wrap your requests in promises and then use Promise.all(...) like so:
const makeRequest = () => {
return new Promise((resolve, reject) => {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
resolve(xhttp.responseText); // On success, resolve the promise
} else {
reject(); // On failure, reject it
}
};
xhttp.open("GET", "filename", true); // Needs to be set to your needs. This is just an example
xhttp.send();
});
}
// This waits until all promises are resolved
const [result1, result2] = await Promise.all(makeRequest(), makeRequest());
// do stuff here with your results
console.log(result1);
console.log(result2);
PS: Basic Ajax example is from here, but just swap it for yours and create parameters or similar to make the requests you actually need
OR
You could use a library like Axios for Ajax requests, which already returns Promises by default. Check it out here: https://github.com/axios/axios

What is the best approach in handling multiple REST API calls for fast retrieving large number of data in JavaScript?

I have two API urls to call the first one is https://jsonplaceholder.typicode.com/todos I need to get this first url to retrieve the id. After retrieving, call the second url which is https://jsonplaceholder.typicode.com/todos/(id). I am using promise-based for this approach, but my problem is.
How to achieve this in fast retrieving the large number of data?
Note: I am using only Plain JavaScript and CDN for axios.
export const getData = () => {
const API = `https://jsonplaceholder.typicode.com/todos`;
return axios.get(API, {
headers: {
"accept": "application/json;odata=verbose"
}
}).then(res => {
const data = [];
const requests = res.map(val => {
const id = val.id;
var obj = {};
const url = `https://jsonplaceholder.typicode.com/todos/(id)`;
return axios.get(url).then(res => {
obj['Result'] = res;
});
});
return Promise.all(requests).then(() => {
return data;
});
});
}
This code is working but it was slow getting the data and I need some suggestions for best concepts.
The fastest way would be to not perform all the AJAX calls from a web browser.
Web browsers cap the number of simultaneous requests around 6–10 (from this post), so if you can perform a request a get a response in 200ms, you're still looking at a full minute of client-side requests.
If instead you built a server-side solution to aggregate the data, you could query your custom endpoint to retrieve larger chunks of data at a time.
If that isn't an option for you, then either way, the browser request limit will probably be your bottleneck.

Why does firestore / AngularFire SDK packs multiple promises to one request?

Here is how I write a document and it's subcollections:
public async setEvent(event: EventInterface): Promise<void[]> {
return new Promise<void[]>(async (resolve, reject) => {
const writePromises: Promise<void>[] = [];
event.setID(event.getID() || this.afs.createId());
event.getActivities()
.forEach((activity) => {
activity.setID(activity.getID() || this.afs.createId());
writePromises.push(this.afs.collection('events').doc(event.getID()).collection('activities').doc(activity.getID()).set(activity.toJSON()));
activity.getAllStreams().forEach((stream) => {
this.logger.info(`Steam ${stream.type} has size of GZIP ${getSize(this.getBlobFromStreamData(stream.data))}`);
writePromises.push(this.afs
.collection('events')
.doc(event.getID())
.collection('activities')
.doc(activity.getID())
.collection('streams')
.doc(stream.type) // #todo check this how it behaves
.set({
type: stream.type,
data: this.getBlobFromStreamData(stream.data),
}))
});
});
try {
await Promise.all(writePromises);
await this.afs.collection('events').doc(event.getID()).set(event.toJSON());
resolve()
} catch (e) {
Raven.captureException(e);
// Try to delete the parent entity and all subdata
await this.deleteEvent(event.getID());
reject('Something went wrong')
}
})
}
However when I look at the network tab:
I see one request firing up, well ok so far , req_0 data is my activity but looking further on the same request I can see:
So it adds more data and that should not happen because:
a) I pass the size of the request to the firestore (1mb)
b) due to slow connection I pass the time limit to write.
Most interesting is that this behavior happens when I have a slow network.
EDIT: Here is the payload of the request example:
Anyone, to explain why this?
What happens is the so-called batching, so your write operations will not fire immediately, they will be aggregated into a single request because doing network I/O is expensive in terms of time and battery life.
Minimizing network I/O saves battery life (as stated above) and that is actually the main concern.
There's "magic" happening under the hood

Categories

Resources