I have a file, tst.html
with the content:
part two
(no markup or anything else, just for demonstration)
And then load said file, via synchronous AJAX (XMLHttpRequest
):
function someFunc() {
var str = 'part one_';
var x = new XMLHttpRequest();
x.open('GET', 'tst.html', false); // "false" for synchronous
x.onreadystatechange = function() {
if(x.readyState === 4) {
switch(x.status) {
case 200:
str += x.responseText.trim();
break;
default:
return ''; // Or something
break;
}
}
}
x.send();
str += '_part three';
return str;
}
Calling the function:
alert(someFunc());
// Returns "part one_part two_part three"
which is the desired behavior.
But if I put the AJAX call into its own function:
function ajaxCall() {
var x = new XMLHttpRequest();
x.open('GET', 'tst.html', false);
x.onreadystatechange = function() {
if(x.readyState === 4) {
switch(x.status) {
case 200:
return x.responseText.trim();
break;
default:
return '';
break;
}
}
}
x.send();
}
function someFunc() {
var str = 'part one';
str += ajaxCall();
str += 'part three';
return str;
}
And then call it:
alert(someFunc());
// Returns "part one_undefined_part three"
The function returns the amalgamated string before the AJAX has a chance to finish, which is identical behavior to its asynchronous cousin.
I've been looking around for something along the lines of "Synchronous AJAX function," but nothing is turning up of any use.
The final use-case of the AJAX call is inside of a recursive set of functions, with further processing dependent on the AJAX return. Something like:
function one(url) {
var x = new XMLHttpRequest();
x.open('GET', url, false);
x.onreadystatechange = function() {
return two(x.responseText.trim());
}
x.send();
}
function two(str) {
var output;
output += stuff;
// ... parse through str
// ... until match found
if(isURL(match)) { // If `match` is a URL
output += one(match);
}else if(isFormattedString(match)) { // if `match` is a string
output += two(match);
}
output += more stuff;
// More processing of output
return output;
}
var final = one(url);
In the example above:
- the system is always initiated with a URL (
one(url)
) one()
returns a string, which itself is the opening argument fortwo(str)
Within
two()
, the parser can encounter eitheranother URL, or
a parseable string.
Depending on which it is, one of the two functions is called
- The output is added to the final result of the system
A callback from one()
won't work on this either, because I still need to have a final return
within two()
.
function one(url, callback) {
// ... AJAX stuff
{
callback(two(x.responseText));
}
}
function two(str) {
// ... same as previous
// The following doesn't work, because then `two()` no longer has a `return`
// ... and any other code (i.e. for !isURL cases) will still continue to execute
if(isURL(match)) {
one(match, function(result) {
output += result;
// ... more processing
return output;
});
}else if(...) {
// ... same as previous
}
// ... more stuffs
}
The only other thing I'm finding is deferred
, but I'm unsure how it would work with this either.
Is there a way to force JavaScript to treat this like other synchronous functions, where the executing code stops until the function is complete? I'm unclear why it doesn't already, with the AJAX request specifically being declared as asynchronous.
Thanks in advance.