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);

在上面的例子中:

来自 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?