I am using axios.interceptors and useContext to handle the request loading spin component in my React.js project.
When the request start, I set the context value - showLoading true, and change to false if it finished or error. The function works perfectly. Here is my sample code:
// Request
axios.interceptors.request.use(request => {
setGlobalLoading(true)
return request;
}, error => {
setGlobalLoading(false);
return Promise.reject(error);
});
// Response
axios.interceptors.response.use(response => {
setGlobalLoading(false);
return response;
}, error => {
setGlobalLoading(false);
return Promise.reject(error);
});
However, I have a page which is a table, and it need to call multiple api on each row, and all the api return so fast. Then it make the loading component "blinking".
So I have an idea, can I make "Only show the loading if the request take more than 1 second " or I should set the delay to close the loading? (But I don't know how to get any pending requests, because this may close the loading when another request not finish)
The callback function only call once, should I use the context or state to save the setTimeout and clearTimeout functions? or any better solution to handle this case?
you can create a array to save requset.
Usually request has a request id,you can use this request id.
if you send a request ,you can push request to array,in finally you can remove this request .
if this array.length >0 loading is show .else loading is close
Related
I'm working on chrome extension. I have function that needs to wait for asynchronous chrome.storage.set to set data and after that use that stored value.
Example: this function is setting access token in chrome storage
async setAuthTokenInStorage(token) {
const dataToStore = {accessToken : token.access_token, refreshToken : token.refresh_token };
chrome.storage.sync.set({ token: dataToStore });
},
After this function, we immediately run one HTTP request in a different place in application. HTTP request will use new token. But that request fails because data is not stored yet, and http request already failed.
Is there some way that we can wait for setAuthTokenInStorage() to finish executing.Meaning that we will make this method 'synchronous' somehow. Goal is to make this function end only when data is stored.
i need to make one of two queries based on the result of another request to a third party, is there a way to tell Apollo to wait for that request to finish and return the appropriate query for Apollo ? or should i just make the request and add the appropriate query manually to Apollo when i get the results ?
thanks to #xadm i was able to get this to work, i am gonna post the vuejs code i reached to do this same effect.
First in my data i should have a variable to skips the query so it won't execute on load...
...
data () {
return {
blockQuery: true
}
}
and then when i am defining my query i should pass that blockQuery to stop it from executing
apollo: {
myDataQuery: {
query: <the gql query>
skip () {
return this.blockQuery // this is true so the query wont execute on load
}
}
}
then i should make whatever third party request i need, for example...
async mounted () {
const response = await <my request that resolves>
// after i made my request i should change the blockQuery to false so it would start the query
this.blockQuery = false // after this changes to false it will start the query.
}
I was wondering if there is any way to cancel/abort a Firebase Realtime Database request when it hasn't returned any results yet.
Consider the following:
1) User selects an item from a list
2) (Web) app makes a request to retrieve some messages or other data for that item
3) The user navigates back and selects a different item
4) The Firebase request returns with results for the wrong item
A regular xhr request can be aborted. A timeout (setTimeout) can be cleared. Is there any way to abort/cancel an ongoing firebase request?
Example:
var request;
// ..
if (request) { abort(request); request = null; }
request = firebase.database().ref("item1/").once("value", callback);
PS: this question is about the database but I guess this would be really handy for most firebase services?
There is no way to abort a read operation.
If you don't want you app to use the data anymore, you can detach the listener by calling off().
This doesn't just work for listeners you register using .on() but also works for .once().
Example:
firebase.db.ref("/item1").once("value", function(snap) { console.log("1: ", snap.val()); });
firebase.db.ref("/item1").off();
firebase.db.ref("/item2").once("value", function(snap) { console.log("2: ", snap.val()); });
Prints the following in the console:
2: { ... }
In other words: the callback from the first line never gets called (unless it returns a result before .off() is called)
There's a webapp that makes a request (let's call it /api/item). This request returns a json body with a field called itemData which is normally hidden from the user, but I want to make that shown.
So how do I make a userscript that listens for the request at /api/item and displays the itemData field?
For reference the way the webapp is making the request is:
return Promise.resolve(new Request(e,r)).then(sendCookies).then(addLangParam).then(addCacheParam).then(addXsrfKey).then(checkZeroRating).then(function(e) {
return fetch(e)
}).then(checkStatus).then(checkApiVersionMismatch).then(checkApiResponse)
Most of that is irrelevant, but the important part is Request (I think).
This webapp is not using XMLHttpRequest, but the Fetch API.
You can use the fetch-intercept npm module to intercept fetch requests. Example code:
import fetchIntercept from 'fetch-intercept'
fetchIntercept.register({
response(response) {
console.log(response)
return response
}
})
Do you have access to the promise returned ?
If so, then you may add another "then".
Otherwise, you may overwrite "checkApiResponse"
I have a form collecting some information that I use $.post to handle an ajax request.
$.post(ajaxEndpoint, dataObject)
.done(function (response) {
if (response.status === 'success') {
// Send data to process asynchronously
otherApiCall(response.otherData);
// Redirect to the thank you page
window.location.replace(getThankYouUrl());
}
});
function otherApiCall (data) {
$.post(otherAjaxEndpoint, data);
}
The problem I have, from what I'm guessing, is that it redirects too quickly before the other POST can be made. But I do want it to POST asynchronously then redirect so the user isn't waiting for that second response. I don't care what the result of the second response is. I just want to finish the first response, send a second POST and the redirect immediately to cut down on the user looking at a spinner.
My second $.post seems like it doesn't get sent in time before the redirect happens because I never get the data from it. If I comment out the redirect, I do. I don't want to wait until the second done() but I can't figure how not to. What am I not understanding and/or doing wrong?
Additional Information/Update
I do have control over the server side handling. Is there something on that end that I could do to get a response quickly without waiting for the rest of the processing to finish?
You probably want to let the second post complete and then do the redirect.
A simple fix would be to return the $.post from second method and use done() of the second call to manage the redirect
$.post(ajaxEndpoint, dataObject)
.done(function (response) {
if (response.status === 'success') {
// Send data to process asynchronously
otherApiCall(response.otherData).done(function(){
// second post call now complete
// Redirect to the thank you page
window.location.replace(getThankYouUrl());
}).fail(function(){
// handle failed response
});
}
});
function otherApiCall (data) {
return $.post(otherAjaxEndpoint, data);
}
The best way to send data back to a server without having to wait for it to complete would be to use the navigator.sendBeacon API.
navigator.sendBeacon('/url/to/handler', yourData);
Quote from MDN:
Using the sendBeacon() method, the data will be transmitted asynchronously to the web server when the User Agent has had an opportunity to do so, without delaying the unload or affecting the performance of the next navigation.
Your data will have to be made into a ArrayBufferView, Blob, DOMString, or FormData, and I'm not sure if it is technically a POST request or not, but the request will persist after redirection.
It is currently supported in Firefox 31+, Chrome 39.0+, Opera 26+. For other browsers, you would have to do something else. You can feature-detect like so.
if (navigator.sendBeacon) {
// Use sendBeacon API.
}
else {
// Something else.
}
The redirect is probably cancelling the AJAX request that has been queued, but not yet sent. Try doing the redirect after a timeout, to give the second AJAX call a chance to be sent.
$.post(ajaxEndpoint, dataObject)
.done(function(response) {
if (response.status === 'success') {
// Send data to process asynchronously
otherApiCall(response.otherData);
// Redirect to the thank you page
setTimeout(function() {
window.location.replace(getThankYouUrl());
}, 10);
}
});
I'm not sure how reliable this is, though. Perhaps a better solution would be to perform the redirect when the second AJAX call goes to readystate == 3, which means the server is processing the request. There's no jQuery interface to this, so you'll probably have to do it using the low-level XMLHttpRequest interface.