JavaScript (Vanilla, no jQuery) - 具有*同步* AJAX (XMLHttpRequest) 调用的函数的行为与异步相同?
JavaScript (Vanilla, no jQuery) - Function with *synchronous* AJAX (XMLHttpRequest) call behaves the same as async?
我有一个文件,tst.html
内容为:
part two
(无标记或其他任何内容,仅用于演示)
然后通过 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;
}
调用函数:
alert(someFunc());
// Returns "part one_part two_part three"
这是期望的行为。
但是如果我将 AJAX 调用放入它自己的函数中:
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;
}
然后调用它:
alert(someFunc());
// Returns "part one_undefined_part three"
函数 return 在 AJAX 有机会完成之前生成合并的字符串,这与其异步表亲的行为相同。
我一直在寻找与 "Synchronous AJAX function," 类似的东西,但没有找到任何有用的东西。
AJAX 调用的最终用例在一组递归函数中,进一步的处理取决于 AJAX return。类似于:
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);
在上面的例子中:
- 系统始终以 URL (
one(url)
) 启动
one()
returns 一个字符串,它本身就是 two(str)
的开始参数
在 two()
内,解析器可能遇到
另一个URL,或
一个可解析的字符串。
看是哪个,调用两个函数中的一个
- 输出添加到系统的最终结果
来自 one()
的回调对此也不起作用,因为我仍然需要在 two()
内有一个最终的 return
。
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
}
我唯一发现的另一件事是 deferred
,但我也不确定它如何与此一起使用。
有没有办法强制 JavaScript 像其他同步函数一样对待它,执行代码停止直到函数完成?我不清楚为什么它还没有,AJAX 请求被明确声明为异步。
提前致谢。
问题是你的return
return x.responseText.trim();
returns 来自处理程序,但不是来自 ajaxCall
函数 - 它没有 return
语句,所以总是 returns undefined
.
我喜欢你的长而详细的问题(希望每个人都尽可能多地提问!),但本质上可以归结为:
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();
}
您的 return
声明是来自 onreadystatechange
的 return,而不是您预期的 ajaxCall
。它与您的原件的唯一区别在于您的原件只是连接字符串。跟移到自己的函数里没关系。
不要使用同步 ajax!了解异步函数的工作原理,尤其是 How do I return the response from an asynchronous call?
我有一个文件,tst.html
内容为:
part two
(无标记或其他任何内容,仅用于演示)
然后通过 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;
}
调用函数:
alert(someFunc());
// Returns "part one_part two_part three"
这是期望的行为。
但是如果我将 AJAX 调用放入它自己的函数中:
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;
}
然后调用它:
alert(someFunc());
// Returns "part one_undefined_part three"
函数 return 在 AJAX 有机会完成之前生成合并的字符串,这与其异步表亲的行为相同。
我一直在寻找与 "Synchronous AJAX function," 类似的东西,但没有找到任何有用的东西。
AJAX 调用的最终用例在一组递归函数中,进一步的处理取决于 AJAX return。类似于:
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);
在上面的例子中:
- 系统始终以 URL (
one(url)
) 启动
one()
returns 一个字符串,它本身就是two(str)
的开始参数
在
two()
内,解析器可能遇到另一个URL,或
一个可解析的字符串。
看是哪个,调用两个函数中的一个
- 输出添加到系统的最终结果
来自 one()
的回调对此也不起作用,因为我仍然需要在 two()
内有一个最终的 return
。
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
}
我唯一发现的另一件事是 deferred
,但我也不确定它如何与此一起使用。
有没有办法强制 JavaScript 像其他同步函数一样对待它,执行代码停止直到函数完成?我不清楚为什么它还没有,AJAX 请求被明确声明为异步。
提前致谢。
问题是你的return
return x.responseText.trim();
returns 来自处理程序,但不是来自 ajaxCall
函数 - 它没有 return
语句,所以总是 returns undefined
.
我喜欢你的长而详细的问题(希望每个人都尽可能多地提问!),但本质上可以归结为:
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();
}
您的 return
声明是来自 onreadystatechange
的 return,而不是您预期的 ajaxCall
。它与您的原件的唯一区别在于您的原件只是连接字符串。跟移到自己的函数里没关系。
不要使用同步 ajax!了解异步函数的工作原理,尤其是 How do I return the response from an asynchronous call?