I need to handle timeouts on my $.ajax() calls for a jQueryMobile project. Doing some research I've come across two viable methods of doing this.
.error() .fail() seems to be generic: if the call fails for any reason then i'm kicked back an error stack, and then the function call is written to handle whatever I need it to.
.timeout, seems to let me deal specifically with timeouts and specify a time period that I can wait, if i don't receive an answer, then the call times out and throws an error.
My question is in a mobile environment, would it be better to handle timeouts with the .timeout() call? Or should I blanket all calls with the .error() .fail() function and handle timeouts within the error callback?
Working with mobile devices it is expected that a user may walk out of a coverage zone, so if the call never returns, my gut would say to implement a timeout function. Do error callbacks have a built in timeout? I would like to handle all errors gracefully, so it seems that maybe a happy medium would be implementing both, and specifying timeouts to work directly with the timeout callback.
Is there anything I might be missing here?
The timeout-event will trigger the fail()-function!
You should set a timeout-value for the $.ajax()-request.
$.ajax({
timeout: 15000 // 15sec
});
If the ajax-request hasn't recieved a response in this period of time it will excecute the function that has been passed in the .fail()-function.
$.ajax()
.fail(function(jqXHR, textStatus, errorThrown) {
if(textStatus === 'timeout') {
alert("$.ajax failed!");
{
});
Related
Mozilla’s documentation on XMLHttpRequest includes the following on the async parameter:
Note: Synchronous requests on the main thread can be easily disruptive to the user experience and should be avoided; in fact, many browsers have deprecated synchronous XHR support on the main thread entirely.
That makes sense, as you don’t what to hold up the main thread waiting for an indeterminate period of time.
If I create an async function which includes usng XMLHttpRequest, would that qualify as a new thread?
I know about fetch(), I know about promises, and I know about using XMLHttpRequest with callbacks. This question is about the async keyword.
JavaScript (in the browser) is entirely single-threaded (with the exception of WebWorkers). The term "asynchronous" doesn't necessarily have anything to do with being multi-threaded.
The network fetch likely happens on browser "networking" thread in a higher performance language (c++, rust, etc.), but this means nothing to JavaScript.
What synchronous means in JavaScript terms is that the c++ code that handles the actual network request will pause the JavaScript event loop until the request completes. That means absolutely nothing can happen in the JavaScript context until the request finishes.
Therefore async means that you can do other things on the single JavaScript thread while the network fetch happens in the background. This is facilitated by c++ calling a JavaScript callback or resolving a JavaScript Promise (aka async/await).
I will try to elaborate more clearly in pseudocode:
const response = makeRequest({ asyncMode: false });
//nothing can happen until this request finishes
//requestAnimationFrame animation code or click event listeners will not run
// until the request is finished
makeRequest({ asyncMode: true, callback: function(response, error){ console.log("this will execute later once the network request is made") } });
console.log("this code will run right away");
//requestAnimationFrame animation code or click event listeners will run as normal
// during the request
Context
We're running some functional unit tests using theintern.io. Unfortunately, third party network calls randomly cause the page to time out, thus causing all of our unit tests to fail.
At a certain point, I'd like to cut the cord on all network calls to prevent the browser from hanging / tests from failing. I've tried window.stop(), but this causes the test to hang.
Question
How can I stop all network calls without also stopping javascript execution of my functional tests?
Firstly, window.stop won't stop javascript execution, in your case it might look like its doing so, if the tests are getting loaded dynamically.
window.stop is same as click stop button on your browser's address bar (Source: https://developer.mozilla.org/en-US/docs/Web/API/Window/stop).
Now coming to your questions, there are multiple ways to handle this, my suggestion would be to mock all the network calls. (Assuming the third party calls that you mentioned are all AJAX). This is also a good practice while writing unit tests. You can use sinon for this. (Source: http://sinonjs.org/)
You can give an expected response, or just give a 404 or anything else, and respond immediately to the requests. That way, your tests won't timeout. Hope it helps
{
beforeEach() {
server = sinon.fakeServer.create();
},
afterEach() {
server.restore()
},
tests: {
testA() {
server.respondWith("GET", /<regexPattern>/,[200, {"Content-Type": "text/plain"},""]);
server.respondImmediately = true;
}
}
}
I'm using socket.io in a Node application. Here is a snippet from my code:
io.sockets.on('connection', socket => {
setTimeout(function () {
console.log('a client connected!')
clients.forEach(s => s.emit('to_client', 'a client connected'))
}, 0)
})
If I remove the setTimeout wrapper, 'a client connected' is not seen in the console of the client (Chrome browser), however, even with a timeout of zero, it does show up. What could be the issue? I would prefer going without the setTimeout since it does not sound like something that should be required here.
Node is an asynchronous single threaded run-time so it uses callbacks to avoid blocking the I/O.
Using the setTimeout is one way (along with nodes built in process.nextTick() method for handling asynchronous code!). Your example code is trying to access clients, I suspect whatever is handling this has not been initialised before your connection callback has executed.
The setTimeout method basically pushes the code (callback function) onto the event queue and therefore anything currently on the call stack will be processed before this setTimeout callback can be run.
First of all, I am well aware that Node.js is non-blocking before anything else, but in this very specific case, it must be blocking and waiting here.
I have an authentication process that works that way (using APIs, I didn't design this so I cannot modify the way the auth works):
I send a PUT request to a REST API, I get a HTTPResponse code that determines if the API understood the request.
The server I just requested through its API sends the full response (including error codes, etc) through an XMPP protocol.
This means, when I send the request, I cannot know what happened next, and must wait for the XMPP event to trigger (basically, an on("message", callback) event).
I'd like to know how to work with this with Node.js.
Two more things to know:
1) I'm working on a client/server architecture, and my Node.js server is doing this authentication process, and sending a response through the websocket to the client and waiting for a socket answer is out of the question (not my call, but my boss wants this process to be done in one pass).
2) It must not be done with the client socket and must go through the full Node.js process for various reasons.
Thanks a lot for your help people! \o/
Sorry for not answering previously, we had some severe hardware failure at work.
Anyway, I'm not answering one of your comments directly because I found a solution I prefer, even if I thank you for your help. I've decided to use a promise and to wait for its answer to be sure to get a proper response.
Here is the code:
var answer = await new Promise((accept, reject) => {
// If there are no stanza in 30 seconds, then the process failed or the stanza got missed.
setTimeout(() => {
reject("timed out");
}, (30 * 1000));
// Waiting for the xmpp event to trigger.
xmpp.on("stanza", function(stanza) {
// Processing of the received stanza goes here.
});
});
#gkatzioura solution was interesting, but this looked a little bit heavy on bandwidth and we are working on a large scale applications, or maybe I didn't fully understand it, then it is my mistake.
#pspi solution was also interesting but this would be a problem considering the XMPP event listener is inside the request, and the PUT request needs to send a body on its end() event and here it wouldn't really work for what I want to do. I think that's because the original post I made was somewhat unclear.
Thanks a lot for your help guys! :]
I don't know enough XMPP, but would this just be case of "putting dependent logic inside callback".
request.put(..., function () {
// dependent xmpp logic inside request callback
xmpp.on(..., function () {
// xmpp and put response received, now talk back to socket client
socket.send(...);
});
});
In your case I would proceed with the event emitter (or anything in a publish subscribe fashion).
Fire your http call and inside the handler add an emitter listener with a check if the events is for the corresponding authentication.
Meanwhile your xmpp connection once it receives the authorization it shall emit a message.
The listener will receive the message successfully and will use the callback of the http call.
I don't see any way to respond to a timeout issue if Facebook is down or not responding when I use FB.init. There's no option here: http://wiki.developers.facebook.com/index.php/JS_API_M_FB.Bootstrap.Init_2
Would be nice if there were some way to respond to errors like you can with normal xmlhttprequests. Is there such a thing with Facebook Connect?
As far as I know, you cannot gracefully handle timeouts with FB.init.
That's why I never use FB.init directly. Instead, I always call FB_RequireFeatures. This wraps the FB.init call so that I can deal with errors and degrade gracefully. What I do is write my own function that checks whether Facebook Connect initialized correctly and then does something appropriate if it did not.
For example:
FB_RequireFeatures(["Connect"], function() {
FB.init("API_KEY", "xd_receiver.htm");
myPostConnectFunction();
});
function myPostConnectFunction() {
// Check for success of FBconnect, and deal with errors accordingly.
};
If that seems hacky, well... it is. :-)