循环中的异步性

我正在使用jQuery的$.getJSON() API从一组实用程序的给定URL中检索数据。 我真的想找到一种方法来重用每个实用程序的代码(它们完全相同)。 由于循环正在执行而不考虑ajax调用,因此我无法找到保留循环值的方法。

我知道,那个描述很糟糕,所以这里是一个代码片段,它将它定义得更好一些:

 var utility_types = [ 'Electricity', 'Gas', 'Water' ]; /** Retrieve known utility providers for the given zip code */ for( var i = 0; i < utility_types.length; i++ ) { var type = utility_types[i]; $.getJSON( '/addresses/utilities/' + zip + '/' + type + '.json', null, function( data, status ) { alert( 'Processing ' + type ); }); } 

我需要找到一种方法将类型值传递给回调,以便我可以应用正确的语法。 没有它,所有3个循环都针对“Water”实用程序执行。 我知道为什么它不起作用,我只是想知道是否有一个合理的解决方法。

谢谢。

创建一个闭包

 var utility_types = [ 'Electricity', 'Gas', 'Water' ]; function getCallBack(type){ return function(data,status){ alert( 'Processing ' + type ); } } /** Retrieve known utility providers for the given zip code */ for( var i = 0; i < utility_types.length; i++ ) { var type = utility_types[i]; $.getJSON( '/addresses/utilities/' + zip + '/' + type + '.json', null, getCallBack(type)); } 

在使用匿名闭包的同时执行此操作的规范方法是创建一个新的匿名闭包,该闭包立即调用并传递循环变量,然后返回真正的回调。

这个匿名闭包有自己的作用域,它包含自己的变量(包括传递的参数),它可以覆盖外部循环的变量,例如:

 ..., success: (function(type) { return function() { alert(type); } }(type)) 

外部括号中的type是循环变量。 函数声明中的type是一个参数 ,它在新闭包的范围内。 调用alert ,它使用范围最接近的alert ,即参数。

当然,参数可以有自己的变量名,它不必与外部作用域中的变量名相同! 如果它不同,则两者都可用,但外部范围的版本将始终具有相同的值。

您可以为每个ajax请求的成员变量分配’type’值,并在回调成功函数中使用this关键字对其进行测试:

 var utility_types = [ 'Electricity', 'Gas', 'Water' ]; /** Retrieve known utility providers for the given zip code */ for( var i = 0; i < utility_types.length; i++ ) { var type = utility_types[i]; var jsonReq = $.getJSON( '/addresses/utilities/' + zip + '/' + type + '.json', null, function( data, status ) { alert( 'Processing ' + this.utilityType ); }); jsonReq.utilityType = type; }