【问题标题】:Loop in function not working循环功能不起作用
【发布时间】:2012-07-18 19:20:33
【问题描述】:

我在循环时遇到了这个小麻烦,我总是得到相同的“y”值 (5),它不会减少或增加。我想要的是重复 ajax 调用 X 次 [all] 并通过匿名函数传递响应和当前调用号码。我希望你能帮助我。

function _shds(long, count, func) {
    for (var y = 0; y < count; y++) {
        gapi.client.load('urlshortener', 'v1', function() {
            var request = gapi.client.urlshortener.url.insert({
                'resource': {
                    'longUrl': long
                }
            });
            var resp = request.execute(function(resp) {
                func(resp.id, y);
            });
        });
    }
}
var total = 3;
var base = "soem";
var lista = ["1", "2", "3", "4", "5"];
_shds("222", total, function(data, y) {
    if (data != "undefined") {
        newbase = base.replace("soem", data);
        console.log(lista[y].uid + newbase + " pos:" + y);
    }
});​

更新:抱歉,这是代码示例:http://jsfiddle.net/ZgXZB/

【问题讨论】:

  • 尝试将 i 复制到另一个变量,然后将该变量传递给调用。像var j = i; 然后call(data, j);
  • @MrOBrian JavaScript 变量具有函数作用域,而不是块作用域。
  • 你的意思是你从服务器得到了5倍的相同答案?
  • @jtlebi 完全正确,因为我希望改变值。你能检查一下这个jsfiddle吗? jsfiddle.net/ZgXZB
  • 好了,5次同数问题就答完了。然而,服务器也总是返回相同的答案,因为请求是相同的。缩短相同的 URL 导致返回相同的短 URL。

标签: javascript jquery loops for-loop


【解决方案1】:

这是一个比最初看起来更棘手的问题,也是一个常见的 JavaScript 陷阱。当你说:

for (var y = 0; y < count; y++) {
    gapi.client.load('urlshortener', 'v1', function() {
        var request = gapi.client.urlshortener.url.insert({
            'resource': {
                'longUrl': long
            }
        });
        var resp = request.execute(function(resp) {
            func(resp.id, y);
        });
    });
}

您正在传递给get 的函数回调中在y 上创建一个闭包。但是,您只创建了一个闭包,它的最终值为y,即count。你要做的是创建count不同的闭包,所以你需要引入一个新的范围:

for (var y = 0; y < count; y++) {
 (function (y){      
  gapi.client.load('urlshortener', 'v1', function() {
      var request = gapi.client.urlshortener.url.insert({
          'resource': {
              'longUrl': longurl
          }
      });
      var resp = request.execute(function(resp) {
          func(resp.id, y);
      });
  });
 })(y);      
}

我认为应该这样做。您需要声明一个新函数以在 JavaScript 中创建新范围,并通过将 y 作为参数传递给该函数,您将为 y 的每个值创建一个新闭包。

【讨论】:

  • 当我转到Run 时,小提琴对我不起作用,但我根据你的新 sn-p 更新了我的代码。这能解决您的问题吗?
  • 小提琴只是将内容推送到控制台。请检查一下,它不适用于您的代码 --> jsfiddle.net/ZgXZB/2
  • @Luis - 很抱歉,这个效果更好 - jsfiddle.net/ZgXZB/3
  • 当然可以,我会选择这个答案,但在此之前,你能纠正循环时的混乱吗?有时它会抛出 0、2、1 或 2、0、1。这很奇怪。
  • 排序取决于哪些网络请求首先完成,并且不能保证,因为一切都是异步执行的。如果您需要按顺序执行函数,那么您需要让回调将每个结果存储到一个数组中并跟踪哪些结果已完成。当它们都完成后,最后一个处理程序将需要调用另一个函数来处理返回的数据。同样,只有当您需要按顺序执行它们时...
【解决方案2】:

问题是您试图获取i 的值回调返回之后,即你的for循环完成之后。你需要做的是bindi的值,当你第一次为$.get构造中间回调时,你想要传递给回调:

function _short(longurl, count, func) {
    for (var y = 0; y < count; y++) {
        gapi.client.load('urlshortener', 'v1', function() {
            var request = gapi.client.urlshortener.url.insert({
                'resource': {
                    'longUrl': longurl
                }
            });
            var resp = request.execute((function(y, resp) {
                func(resp.id, y);
            }).bind(this, y));
        });
    }
}
var totalchat = 10;
var base = "soem";
var listachat = ["1", "2", "3", "4", "5"];
_short("222", 3, function(data, y) {
    if (data != "undefined") {
        newbase = base.replace("soem", data);
        console.log(listachat[y].uid + newbase + " pos:" + y);
    }
});

bind 所做的是创建一个新函数,其中this 的值绑定到第一个参数(我刚刚设置为this),所有剩余的参数都绑定到函数的第一个参数,而它返回的函数需要一组新的参数(在这种情况下,只有 data 参数来自原始函数,它与 $.get 的回调签名匹配)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2020-08-08
    相关资源
    最近更新 更多