for 循环中的 JavaScript 异步调用

javascript async call in a for loop

本文关键字:异步 调用 JavaScript 循环 for      更新时间:2023-09-26

菜鸟问题。这可能是一个重复的,但我无法理解如何重组代码。我应该如何构建以下代码,以便控制台打印以下内容:

这里1这里2这里1这里2这里1这里2

现在它去:

这里1这里1这里1这里2这里2这里2

感谢您的帮助。

var record;
for ( i = 0; i < 3; i++ ) {
    sendRequest(selectTestsToRun('something1'), 'someTest1');
}
this.someTest1 = function(resObj, testToRun){
    console.log('Here1');
    record = resObj.value;
    sendRequest(selectTestsToRun('something2'), 'someTest2');
};
this.someTest2  = function(resObj, testToRun){
    console.log('Here2');
};
function selectTestsToRun(toDo){
    var data;
    switch( toDo) {
        case 'something1':
            data = 'postMessage';
            break;
        case 'something2':
            data = 'postMessage'+record;
            break;
    }
    return data;
}
function sendRequest(data , toDo ){
    GM_xmlhttpRequest({
        method: 'POST',
        url:  url,
        data: data,
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        onload: function(response) {
            var resObj = JSON.parse(response);
            this[toDo](resObj,toDo);
        }
    });
}

你根本不想要一个for循环。相反,您希望someTest2启动"循环"的下一次迭代:

var i = 0;
next();
function next() {
    if (i < 3) {
        sendRequest(selectTestsToRun('something1'), 'someTest1');
        ++i;
    }
}
this.someTest2  = function(resObj, testToRun){
    console.log('Here2');
    next();                                          // <==== Note
};

在上面,我已将其烘焙到someTest2中,但是您当然可以传递回调以将循环与someTest2解耦。

您必须记住,当循环同步执行时,AJAX 调用是异步发生的。

循环背靠背调用 test1,而 AJAX 请求至少需要 300 毫秒才能往返服务器。这肯定会在循环结束后很长时间内发生。

你需要使用回调(或承诺)来调用下一个函数。 您可以将确定下一步要调用哪一个的逻辑放在回调中。 下面是一个使用 jQuery 进行 Ajax 通信的示例。

我走老派,使用了一个计数器,该计数器仅由第一个调用函数递增。当计数器达到您的极限时,它就像一个开关并停止粘性循环。

你可以在这里看到它的工作原理:https://jsbin.com/wohife/

$(document).ready(function() {
    var counter = 0;

    function test1() {
        if (counter < 3) {
            sendRequest(1);
            console.log('here 1');
        }
        counter++;
    }
    function test2() {
        sendRequest(2);
        console.log('here 2');
    }
    function sendRequest(requesterId) {
        $.ajax({
            url: 'https://jsbin.com/sohefe/1.json',
            type: 'GET'
        })
        .success(function(data, status, req) {
            if (requesterId === 1) {
                test2();
            }
            else {
                test1();
            }
        });
    }
    test1();
});