Reputation: 26008
Here is a javascript function:
function getValue(key) {
var value;
switch(_options.myType){
case "cookie":
value = readFromCookie(key);
break;
case "localStorage":
value = readFromLocalStorage(key);
break;
case "db":
//return value from the server
// how do I wait for the result?
$.ajax({
type: "GET",
url: "123",
data: { .... },
success: function(data){
value = data;
}
});
break;
}
return value;
};
In case of sending ajax request, I need to wait untill the ajax request has been completed. How can I do it?
Not that I can't leave the function without having the value calculated. Which means that I can't place a function inside success:
handler which will return the value later (or perhaps I don't understand something?). So it must be calculated within the function getValue()
.
UPDATE
P.S. So how do refactor my code to be able to use callback inside success:
handler? Here is the second part of the code:
MyClass123.prototype.myMethod = function(value) {
//..............
var var1 = this.getValue("key1");
if (var1 == "123") { ... }
else { .... }
//..............
}
};
Upvotes: 0
Views: 3007
Reputation: 1073968
See follow-up below
You could make the ajax request synchronous, but that's generally a bad idea (and jQuery won't support it much longer).
Instead, make getValue
accept a callback:
function getValue(key, callback) {
switch(_options.myType){
case "cookie":
setTimeout(function() {
callback(readFromCookie(key));
}, 0);
break;
case "localStorage":
setTimeout(function() {
callback(readFromLocalStorage(key));
}, 0);
break;
case "db":
//return value from the server
// how do I wait for the result?
$.ajax({
type: "GET",
url: "123",
data: { .... },
success: function(data){
callback(data);
}
});
break;
}
}
Note that I'm using setTimeout
for the readFromCookie
and readFromLocalStorage
callbacks. Why? Because if getValue
might return its value asynchronously, it should always do so. using a timeout of 0
asks the browser to do it as soon as possible once control yields back to the browser (although it's usually clamped to no less than 5-10ms).
Re your comment below:
Have you read what I write? I said that I can't do it for some reason.
I missed that bit, but with all due respect, you can. It may require some refactoring of code, but you can do it, and should. This is how modern web applications work. If your structure doesn't support it, you need to fix the structure. You can use async: false
on the request as a temporary workaround until you can do it properly. (Hey, we've all been there and had to do things like that.) Note that it's scheduled for retirement before too long (just jQuery's support of it, you'll still be able to use XHR directly to do synchronous requests).
Re your updated question, here's how you update that code:
MyClass123.prototype.myMethod = function(value) {
this.getState("key1", function(var1) {
// ^--- Note the var becomes an arg
if var1 == "123"{ ... }
else { .... }
});
};
Note how little it actually changes. The logic that used to follow the call to getState
instead goes into the callback you pass into it.
Upvotes: 8
Reputation: 66663
You can make the AJAX request synchronous by specifying async: false
- which is not recommended but possible. If it absolutely is the case that your getValue()
function should not return before the AJAX request returns, then async
is the way to go.
$.ajax({
type: "GET",
url: "123",
async: false // NEW
data: { .... },
success: function(data){
value = data;
}
});
Alternative using then
and when
:
function getValue(key, callback) {
switch(_options.myType){
...
case "db":
return $.ajax({ // note the 'return'
type: "GET",
url: "123",
...
});
}
}
and where you call it, call it like:
$.when(getValue()).then(function() {
// do the rest here ...
});
Upvotes: 2
Reputation: 449385
The right thing to do is to restructure your program flow so you can place your logic in the success
handler.
You can make Ajax requests synchronous by using the async
option, but that is silly. It'll slow down your app, because the browser window freezes until the request comes back successful (or times out). It's not often used in JavaScript development and for good reason.
Upvotes: 2