做项目的时候,栽在一个小地方,是这样的
我有很多个坐标点,我想把这些坐标点都绑定一个事件,当点击了这个坐标点之后,发送一个ajax 请求,将坐标点的id 发出去,等待显示返回的数据
但是实际当中,无论我点击了哪个点,都发现发送的ajax 请求都是最后一个点的id值上,
仔细一想,确实是这么回事,因为点击这个事情是异步,当执行ajax的时候,遍历早已结束,所以返回最后一点是正常的。
问题变成了,怎样让回调函数读取到每次的临时变量,也就是个闭包的问题
平时对闭包不是太清楚,所以顺便复习一下了,
参考资料也是博客园朋友写的 http://kb.cnblogs.com/page/110782/
之后也参考了这里 http://*.com/questions/6978911/closure-inside-a-for-loop-callback-with-loop-variable-as-parameter
这里大概这么处理
在循环里写
function build_callback(id){
returnfunction(data, textStatus){
alert(id);
};
}
$.get("XXXX",build_callback(id))
也可以使用匿名函数解决
for (var idx=1; idx<=15; idx++) (function(idx) { var probeIP = siteConfigArray[idx].siteIP; if (probeIP != "" && probeIP != null) jQuery.get("svGetPortInfo.php?svSiteIpAddr=" + probeIP+"&s="+idx, function(data, textStatus) { test(data, textStatus, idx); }, ‘text‘); else // IP value is blank siteConfigArray[idx].portManifest = null; })(idx);
最后,如果有人用coffeescript 来写,那就变得更简单了,只需要在循环里在加一句 do (XXX) ->
coffeescript就会自动生成好闭包,这里是我的代码
for node in stations do (node) -> point = new BMap.Point(node.lng,node.lat) marker = new BMap.Marker(point) label = new BMap.Label(node.name, {offset: new BMap.Size(20, 4)}) marker.setLabel(label) contextMenu = new BMap.ContextMenu() contextMenu.addItem(new BMap.MenuItem("查看 #{node.name} 详情", () -> $.get("stations/#{node.id}",(data)-> eval data ) , 200)) window.map.addOverlay(marker) marker.addContextMenu(contextMenu)
coffeescript 也给出了官方例子
for filename in list do (filename) -> fs.readFile filename, (err, contents) -> compile filename, contents.toString()
会对应生成这样的js
var filename, _fn, _i, _len; _fn = function(filename) { return fs.readFile(filename, function(err, contents) { return compile(filename, contents.toString()); }); }; for (_i = 0, _len = list.length; _i < _len; _i++) { filename = list[_i]; _fn(filename); }