Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript $.get in a loop:为什么函数在递增后执行?_Javascript_Jquery_Loops_Get - Fatal编程技术网

Javascript $.get in a loop:为什么函数在递增后执行?

Javascript $.get in a loop:为什么函数在递增后执行?,javascript,jquery,loops,get,Javascript,Jquery,Loops,Get,我是Javascript的初学者,我觉得$.get jQuery有些问题 通常,您可以将其分配给一个函数,该函数将在正确检索数据后执行 但是,如果我将$.get放入一个循环中,即使尚未检索到数据,循环也会继续执行,这就是我的问题 这是我的代码(这是给GreaseMonkey的): var1=document.getElementsByClassName(“some_类”); i=0; 而(i

我是Javascript的初学者,我觉得$.get jQuery有些问题

通常,您可以将其分配给一个函数,该函数将在正确检索数据后执行

但是,如果我将$.get放入一个循环中,即使尚未检索到数据,循环也会继续执行,这就是我的问题

这是我的代码(这是给GreaseMonkey的):

var1=document.getElementsByClassName(“some_类”);
i=0;
而(i
在这里,如果警报返回1(例如),则返回var1.length事件

我尝试在url声明之后添加一个警报(I),我知道I++是在我的$.get中的函数之前完成的


这当然是一个微不足道的问题,但我无法理解不发生这种情况的逻辑。

将您的
$包装起来。因此获取
函数:

(function(i) {
    $.get(url, function(data) {
        if (data.contains("some_string")) {
            alert(i);
        }
    });
})(i);
立即调用的函数表达式通过函数的参数
i
(随后隐藏外部变量)绑定外部范围中的
i
的当前值。如果愿意,请为函数参数指定一个不同的名称

请注意,这只修复了您实际提到的问题,即循环变量的增量与回调无关。如果您希望确保AJAX请求一次运行一个,那么还有其他解决方案,例如:

var els = document.getElementsByClassName("some_class");
var i = 0;

(function loop() {
    if (i < els.length) {
        var el = els[i];
        var url = el.getElementsByTagName("some_tag")[0].href;
        $.get(url).done(function(data) {
            if (data.contains("some_string")) {
                alert(i);
            }
            i++;
        }, loop);   // .done(f1, f2) - see below
     }
})();
var els=document.getElementsByClassName(“some_类”);
var i=0;
(函数循环(){
如果(i

.done()
调用的形式为
.done(回调,循环)
,将按顺序调用这两个函数。因此,
i++
行总是首先出现,然后它安排以伪递归方式调用
循环
,以处理下一个元素。

包装
$。因此,获取
函数:

(function(i) {
    $.get(url, function(data) {
        if (data.contains("some_string")) {
            alert(i);
        }
    });
})(i);
立即调用的函数表达式通过函数的参数
i
(随后隐藏外部变量)绑定外部范围中的
i
的当前值。如果愿意,请为函数参数指定一个不同的名称

请注意,这只修复了您实际提到的问题,即循环变量的增量与回调无关。如果您希望确保AJAX请求一次运行一个,那么还有其他解决方案,例如:

var els = document.getElementsByClassName("some_class");
var i = 0;

(function loop() {
    if (i < els.length) {
        var el = els[i];
        var url = el.getElementsByTagName("some_tag")[0].href;
        $.get(url).done(function(data) {
            if (data.contains("some_string")) {
                alert(i);
            }
            i++;
        }, loop);   // .done(f1, f2) - see below
     }
})();
var els=document.getElementsByClassName(“some_类”);
var i=0;
(函数循环(){
如果(i
.done()
调用的形式为
.done(回调,循环)
,将按顺序调用这两个函数。因此,
i++
行总是首先发生,然后它安排以伪递归方式调用
循环
,以处理下一个元素。

供您进一步研究

$("#output").empty();

var startTime = new Date().getTime();

// try experimenting with async = true/false and the delay
// don't set async to false with too big a delay,
// and too high a count,
// or you could hang your browser for a while!
// When async==false, you will see each callback respond in order, followed by "Loop finished".
// When async==true, you could see anything, in any order.
var async = true;
var delay = 1;
var count = 5;

function createClosure(i) {
    // return a function that can 'see' i.
    // and i's remains pinned within this closure
    return function (resp) {
        var duration = new Date().getTime() - startTime;
        $("#output").append("\n" + i + " returned: " + resp + " after " + duration + "ms");
    };
}

for (var i = 0; i < count; i++) {
    // jsfiddle url and params
    var url = "/echo/html/";
    var data = {
        html: "hello " + i,
        delay: delay
    };

    $.ajax(url, {
        type: "post",
        data: data,
        async: async
    }).then(createClosure(i));
}

var duration = new Date().getTime() - startTime;
$("#output").append("\n" + "Loop finished after " + duration + "ms");
示例
async=false
输出(浏览器挂起5558ms!):

供你进一步调查

$("#output").empty();

var startTime = new Date().getTime();

// try experimenting with async = true/false and the delay
// don't set async to false with too big a delay,
// and too high a count,
// or you could hang your browser for a while!
// When async==false, you will see each callback respond in order, followed by "Loop finished".
// When async==true, you could see anything, in any order.
var async = true;
var delay = 1;
var count = 5;

function createClosure(i) {
    // return a function that can 'see' i.
    // and i's remains pinned within this closure
    return function (resp) {
        var duration = new Date().getTime() - startTime;
        $("#output").append("\n" + i + " returned: " + resp + " after " + duration + "ms");
    };
}

for (var i = 0; i < count; i++) {
    // jsfiddle url and params
    var url = "/echo/html/";
    var data = {
        html: "hello " + i,
        delay: delay
    };

    $.ajax(url, {
        type: "post",
        data: data,
        async: async
    }).then(createClosure(i));
}

var duration = new Date().getTime() - startTime;
$("#output").append("\n" + "Loop finished after " + duration + "ms");
示例
async=false
输出(浏览器挂起5558ms!):


由于您使用的是jQuery,因此可以大大简化代码:

$('.some_class').each( function( i, element ) {
    var url = $(element).find('some_tag')[0].href;
    $.get( url, function( data ) {
        if( data.contains("some_string") ) {
            alert( i );
        }
    });
});
对原始代码的更改包括:

  • jQuery调用而不是
    getElementsBy*
    函数
  • jQuery
    .each()
    用于循环
  • 在需要时添加缺少的
    var
    。(在任何版本的代码中都非常重要!)
  • 请注意,使用
    .each()
    会自动提供与另一个答案中立即调用的函数表达式(IIFE)相同的效果,但不会带来额外的复杂性。这是因为
    .each()
    始终使用回调函数,这将创建所需的闭包,以便为循环的每次迭代唯一地保留
    i
    变量(以及
    元素

    当您有一个普通的
    while
    for
    循环,并且您仍然不需要iLife时,您也可以这样做。相反,只需在循环中调用函数即可。以这种方式编写的代码将是:

    var $elements = $('.some_class');
    for( var i = 0;  i < $elements.length;  i++ ) {
        checkElement( i, $elements[i] );
    }
    
    function checkElement( i, element ) {
        var url = $(element).find('some_tag')[0].href;
        $.get( url, function( data ) {
            if( data.contains("some_string") ) {
                alert( i );
            }
        });
    }
    
    var$elements=$('.some_class');
    对于(变量i=0;i<$elements.length;i++){
    检查元素(i,$elements[i]);
    }
    功能检查元素(i,元素){
    var url=$(元素).find('some_标记')[0].href;
    $.get(url、函数(数据){
    if(data.contains(“某些字符串”)){
    警报(一);
    }
    });
    }
    
    如您所见,
    checkElement
    函数与
    .each()
    回调函数相同。实际上,
    .each()
    只是为您运行一个类似的
    for
    循环,并以与此代码完全相同的方式调用回调。此外,for
    循环的
    比while
    循环更可读,因为它将所有循环变量操作放在一个地方。(如果您不熟悉
    for
    循环语法,一开始可能会觉得可读性较差,但一旦习惯了,您可能会发现您更喜欢
    for
    循环。)

    一般来说,当试图在循环中间使用iFIE时,尝试将代码拆分为完全分离的函数。在许多情况下,它会导致更可读的代码。

    Sin