当最里面的循环等待响应时,如何延迟嵌套迭代?

时间:2015-11-22 20:23:02

标签: javascript jquery ajax callback jquery-callback

以下是我的问题陈述的概述:

我正在尝试为在线多选问卷表单生成解决方案。我们的想法是编写一个javascript函数,遍历所有问题并找到正确的答案。

为了简单起见,我将只尝试一个由levelNoquestionNo变量唯一标识的问题,选择一个选项,通过javascript提交form,从而提交一个对所选问题的回答并跳过所有其他问题。

表单提交中的result是正确回复的数量。因此,如果表单提交中的result"1",则选择的选项是正确的,否则错误。我一直在迭代每个问题的选项,直到我找到正确的答案。

典型的同步性问题

现在,问题是表单提交需要相当长的时间,我的javascript代码会继续执行,而不会等待请求完成并返回响应。我希望延迟迭代,直到响应加载。

function solve(){
    var options = ['a', 'b', 'c', 'd'];
    for(var levelNo = 1; levelNo<=5; levelNo++){
        for(var questionNo = 1; questionNo <=10; questionNo++){
            var solved = false;
            for(var i=0; i<4 && !solved; i++){
                var questionId = levelNo+'_'+questionNo; 

                $.ajax({
                    method:"POST", 
                    url: "get_scores.php",
                    data : questionId+'='+options[i]
                }).done(function (data, textStatus, jqXHR) {
                    var sectionScore = $(data).text().trim();               
                    if(sectionScore == "1"){
                        solved = true;
                        console.log(questionNo+"->"+options[i]);    
                    }   
                });                 
            }           
        }
    }
}

正如我们所看到的,我通过jQuery.done()调用AJAX解决了一个请求的问题。但是,我无法为迭代解决这个问题。

我理解我的方法的设计在同步意义上是完全错误的,因为我每次都在等待响应,然后再进行迭代。我可以使用顺序XMLHttpRequest解决问题,并在jQuery AJAX中将async设置为false。

但我希望探索这种方法,希望/期望更多地了解回调/闭包,因为我的研究已经看到很多帖子都在谈论回调作为解决这类问题的潜在解决方案。

因此,出于学术兴趣,我想知道上述问题是否可以使用异步请求和回调来解决。如果是这样,怎么样?如果没有,为什么回调的概念不适用于此sceanrio?是否还有其他可以使用的javascript原则?

TL; DR :我希望延迟嵌套迭代,直到来自网站的JSON响应加载。回调可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

这应该有效,但请注意我总是检查所有答案。如果您已经有正确的答案,更好的方法应该避免再次呼叫同一个问题。

var options = ['a', 'b', 'c', 'd'];

var answers = [];
var solutions = {};
var requestScore = function(questionId,optionSelected){
    $.ajax({
        method:"POST", 
        url: "get_scores.php",
        data : questionId+'='+optionSelected
    }).done(function (data, textStatus, jqXHR) {
        var sectionScore = $(data).text().trim();               
        if(sectionScore == "1"){
            solutions[questionId] = optionSelected;
        }
        if ( answers.length > 0 ){
            requestScore.apply( this, answers.shift() );
        }else console.log( solutions ); //your solutions
    });
};

for(var levelNo = 1; levelNo<=5; levelNo++){
    for(var questionNo = 1; questionNo <=10; questionNo++){
        for(var i=0; i<4; i++){
            var questionId = levelNo+'_'+questionNo; 
            answers.push( [questionId,optionSelected] );//wherever optionSelected comes from               
        }           
    }
}

requestScore.apply( this, answers.shift() );

答案 1 :(得分:0)

我提出了以下解决方案,这似乎对我有用。但是,我正在进行递归调用以重新尝试每个问题,从而实现数据的同步。

var options = ['a', 'b', 'c', 'd'];
var answers = [];
var solutions = [];

function attempt(levelNo, questionId, optionSelected){
    $.ajax({
        method:"POST", 
        url: "get_scores.php",
        data : questionId+'='+optionSelected,           
        success : function (data){
            var sectionScore = $(data).text().trim();    
            if(sectionScore == "1"){
                solutions[questionId] = optionSelected;             
                answers.push( [questionId, optionSelected] );              
                console.log(solutions);  
            } else{
                // Keep trying with the next option.        
                var nextOption = options[options.indexOf(optionSelected)+1];
                attempt(levelNo, questionId, nextOption);                       
            }           
        }
    });
};

function solve(){
    for(var levelNo = 1; levelNo<=1; levelNo++){
        for(var questionNo = 1; questionNo <=4; questionNo++){
            var questionId = levelNo+"_"+questionNo; 
            attempt(levelNo, questionId, options[0]); // start with first option
        }
    }
}
solve();