JavaScript(Vanilla,没有jQuery) - 具有* synchronous * AJAX(XMLHttpRequest)调用的函数与async的行为相同吗?

时间:2016-09-01 13:19:52

标签: javascript ajax synchronous

我有一个文件tst.html,内容为:

part two

(没有标记或其他任何内容,只是为了演示)

然后通过 同步 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"

该函数在AJAX有机会完成之前返回合并的字符串,这与其异步表兄相同。

我一直在寻找“同步AJAX功能”中的某些内容,"但没有任何用处。

AJAX调用的最终用例是在一组递归函数内部,进一步处理依赖于AJAX返回。类似的东西:

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(url)
  • 启动
  • one()返回一个字符串,它本身就是two(str)
  • 的开头参数
  • two()内,解析器可以遇到

    1. 另一个网址,或

    2. 一个可解析的字符串。

  • 根据它的不同,两个函数之一称为

  • 将输出添加到系统的最终结果

来自one()的回调也不会对此产生影响,因为我仍然需要在return内设置最终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
}

我发现的唯一另一件事是deferred,但我不确定它是如何运作的。

有没有办法强制JavaScript像其他同步函数一样处理它,执行代码会停止,直到函数完成?我不清楚它为什么还没有,因为AJAX请求被特别声明为异步。

提前致谢。

2 个答案:

答案 0 :(得分:6)

我喜欢你冗长而详细的问题(希望每个人都尽可能多地投入询问!),但实质上它归结为:

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的回复,而不是您预期的ajaxCall。它与原始版本的不同之处在于您的原始文件只是连接字符串。它与将其移动到自己的功能无关。

不要使用同步ajax!了解异步函数的工作方式,尤其是How do I return the response from an asynchronous call?

答案 1 :(得分:1)

问题在于您的val3

return

从处理程序返回,但不是从return x.responseText.trim(); 函数返回 - 它没有ajaxCall语句,所以总是返回return