【问题标题】:Using Javascript closure to pass additional data to an API callback function使用 Javascript 闭包将附加数据传递给 API 回调函数
【发布时间】:2012-03-01 17:32:52
【问题描述】:

我已经让它工作了一点,但似乎无法弄清楚让 for 循环传递正确值的确切措辞是什么。

for(i=0; i < the_stores.length; i++) {
    uid = the_stores[i].id;

    // get the lat long and write info to the console
    geocoder.getLatLng(the_stores[i].address, function(point) { return callbackFunc(point, uid); });
}

function callbackFunc(point, myID) {
    if(point !== null) {
        console.log(point.toString());
        console.log(myID);
    } else {
        return false;
    }
}

我正在使用 Google Maps API v2。我希望 for 循环在循环的每次迭代中将不同的 uid 值传递给回调函数,但现在它每次都传递相同的值。有人知道如何在这里获得所需的效果吗?我觉得我很接近。谢谢!

【问题讨论】:

标签: javascript google-maps asynchronous callback closures


【解决方案1】:

您正在寻找的是“立即调用函数表达式”。由于 JavaScript 只有函数作用域,没有块作用域,所有对 uid 的引用都绑定到同一个变量。

(更多信息请见:http://benalman.com/news/2010/11/immediately-invoked-function-expression/

这是一个简单的方法:

for(i=0; i < the_stores.length; i++) {
  (function() {
    var uid = the_stores[i].id;

    // get the lat long and write info to the console
    geocoder.getLatLng(the_stores[i].address, function(point) { return callbackFunc(point, uid); });
  })();
}

【讨论】:

  • 嗯,它仍在输出相同的 ID。您在第二行定义的匿名函数应该在哪里使用?感谢您的帮助。
  • 立即调用。另外,请确保在 uid 声明前添加 var,否则它将不起作用。
  • 您是否编辑了您的原始回复,或者我只是感到困惑?无论如何,这行得通!非常感谢,我一直在努力解决这个问题。
  • 没问题。我最终没有编辑它,尽管你确实把我送回我的控制台以确保它正常工作:)
【解决方案2】:

使用您的callbackFunc 返回一个引用需要保留的值的处理程序。

for(i=0; i < the_stores.length; i++) {

    // get the lat long and write info to the console
    geocoder.getLatLng(the_stores[i].address, callbackFunc(the_stores[i].id));
}

function callbackFunc(myID) {
    return function(point) {
        if(point !== null) {
            console.log(point.toString());
            console.log(myID);
        } else {
            return false;
        }
    };
}

【讨论】:

    【解决方案3】:

    这就是我如此喜欢Array.forEach() 的原因。它会为您处理所有这些常见的循环问题。像这样使用它:

    the_stores.forEach(function (store, i) {
        geocoder.getLatLng(store.address, function(point) {
            return callbackFunc(point, store.id);
        });
    }
    

    Array.forEach() 是现代浏览器中的原生 JavaScript,但对于 IE8 和 IE7,您需要自己添加。我推荐使用implementation provided by MDN。在我看来,至少包含所有新的 Array 方法的 JS5 shim 应该是任何网站的样板。

    【讨论】:

    • 这是一个方便的解决方案,当你可以摆脱它时,但值得注意的是,填充 Array.prototype.forEach 有其自身的后果,即迭代 Array 对象属性将出现 forEach 在那些浏览器。 (也许很少见,但有时很棘手。)
    • @Paul - for..in 用于枚举,而不是迭代。当他们打算迭代时犯了枚举错误的开发人员将会并且应该吸取教训。我们不应该因为一些开发者滥用语言而降低我们的编码标准。
    • 我同意 100%。我只是为了完整性添加了我的评论:)
    • @gilly3:+1 为您的回答,尤其是您的评论。编码标准应该基于对语言的理解,而不是其他人无法理解。
    猜你喜欢
    • 1970-01-01
    • 2019-08-09
    • 2014-01-27
    • 2016-09-03
    • 2011-09-20
    • 2011-03-28
    • 2011-10-05
    • 2016-09-19
    相关资源
    最近更新 更多