等待函数 $.get done 中的代码继续

Wait to code inside function $.get done to continue

我正在用 javascript 做一个网站,但我做不到。

我有这个

<script type="text/javascript">
res = new Array();

var fun1 = function () {
var control = $.Deferred();
for (i=0;i<5;i++) {
    $.get("URL", function(data){
        res[i]=data;
        console.log ("i is: " + i + "and res is: " + res);
    });
    }
}

setTimeout(function () {
control.resolve();
}, 3000);

var show = function () {
console.log("Res finally is: " + res);
}

fun1().done(show);  
</script>

我想用 5 个或更多不同的 URL(我在 URL 中有一个参数)做一个 $.get,但我做不到。 res[i] 始终是数组中的最后一个元素(在这种情况下始终是 res[5]=data 并且我想填充完整的数组,从 0 到 15。

首先console.log总是显示

i is:  5 and res is: ,,,,,20
i is:  5 and res is: ,,,,,10
...
i is:  5 and res is: ,,,,,38

第二个console.log总是return最后一个

Res finally is ,,,,,38

我怎样才能正确地做到这一点?

谢谢!

i 的主要问题是您的回调关闭 变量 i,而不是函数创建时的值。所以他们都看到了 i = 5.

我不太明白你为什么要重复 get 五次,但如果你想,你必须给回调一些其他的东西来结束(或使用 res.push(...)而不是 res[i] = ...,但我认为你有理由选择后者。

您可以使用生成器来做到这一点:

// PARTIAL solution, see below
var fun1 = function () {
    var control = $.Deferred();
    for (i=0;i<5;i++) {
        $.get("URL", buildHandler(i));
    }

    function buildHandler(index) {
        return function(data){
            res[index]=data;
            console.log ("index is: " + index + "and res is: " + res);
        };
    }
};

另一种创建构建器的方法是使用 Function#bind(ES5+,但很容易填充),但你会创建比你需要的更多的函数;以上在这种情况下更有效(不是很重要)。

然后,fun1 return 一些有用的东西,你就有了 return 一个承诺(根据你的 control 变量),然后在所有 get 完成后履行承诺($.when 对此很有用):

var fun1 = function () {
    var control = $.Deferred();
    var promises = [];
    for (i=0;i<5;i++) {
        promises.push($.get("URL", buildHandler(i)));
    }
    $.when.apply($, promises).then(function() {
        control.resolve(); // Or .resolveWith(), passing in something useful
    });

    return control.promise();

    function buildHandler(index) {
        return function(data){
            res[index]=data;
            console.log ("index is: " + index + "and res is: " + res);
        };
    }
};

所有这些都假设 res 在此代码的范围内;你还没有显示它的来源。