2013-01-31 39 views
2

我写了一些JavaScript来运行一组“模块”。对于每个模块,它会调用ajax,获取模块的html,并将模块转储到页面布局上的两列之一。如何在ajax回调中保留一个变量?

var modules = [ 
    { name: 'ExchangeStatus', title: 'Exchange Status', column: 'left' }, 
    { name: 'Grid', title: 'Contacts', column: 'right' } 
    { name: 'Filters', title: 'Filters', column: 'left' } 
], 
modulesUrl = '/Modules/'; 

for (var count = 0; count < modules.length; count++) { 
    var module = modules[count]; 

    // Get module HTML. 
    $.ajax({ 
     url: modulesUrl + module.name, 
     success: function (moduleHtml) { 

      // Append module HTML to appropriate element. 
      $('#' + module.column + 'Column').append(moduleHtml); 

      // Custom event to trigger the module to load its data. 
      var initializeModuleEvent = $.Event('initialize' + module.name); 
      initializeModuleEvent.firstLoad = true; 
      $(document).trigger(initializeModuleEvent); 

     } 
    }); 
} 

问题在于for循环创建竞争条件。在ajax回调中,module.column几乎总是最后一个模块的值,因为for循环在ajax回调返回之前很久才完成。我如何维护模块变量,以便每个回调都处理相应的模块?目前,所有三个模块都在左列中结束,因为循环中的最后一个模块位于左列。

+0

可能重复[关闭的Javascript内循环 - 简单实用的例子(HTTP://计算器。 com/questions/750486/javascript-closure-inside-loops-simple-practical-example) –

回答

7

你可以尝试创建一个额外的范围,通过module

for (var count = 0; count < modules.length; count++) { 
    var module = modules[count]; 

    (function(module) { 
     $.ajax({ 
     ... 
     }) 
    }(module)); 

编辑:如果你愿意,你可以使用forEach还有:

modules.forEach(function(module) { 
// 'module' will be available everywhere in this scope 
}); 
+0

非常感谢!我觉得愚蠢的是没有考虑自己使用闭包,但我真的很感激它:D – Chev

+0

这不是唯一的选择,但最明显的。如果你愿意,你可以使用'forEach'并忘记关闭。 – elclanrs

+0

我没有意识到JavaScript有一个'forEach' ...我似乎无法得到它的工作。编辑:哦,阵列本身的功能。尼斯。 – Chev

1

这将有助于

for (var count = 0; count < modules.length; count++) { 
    var module = modules[count]; 

    (function (module) { 
     // Get module HTML. 
     $.ajax({ 
      url: modulesUrl + module.name, 
      success: function (moduleHtml) { 

       // Append module HTML to appropriate element. 
       $('#' + module.column + 'Column').append(moduleHtml); 

       // Custom event to trigger the module to load its data. 
       var initia`enter code here`lizeModuleEvent = $.Event('initialize' + module.name); 
       initializeModuleEvent.firstLoad = true; 
       $(document).trigger(initializeModuleEvent); 

      } 
     }); 
    })(module) 
} 
2

修改您的成功callb确认此:

$.ajax({ 
    url: modulesUrl + module.name, 
    success: (function (module) { 
     return function (moduleHtml) { 
      // Append module HTML to appropriate element. 
      $('#' + module.column + 'Column').append(moduleHtml); 

      // Custom event to trigger the module to load its data. 
      var initializeModuleEvent = $.Event('initialize' + module.name); 
      initializeModuleEvent.firstLoad = true; 
      $(document).trigger(initializeModuleEvent); 
     }; 
    }(module)); 
}); 

这将创建一个新的范围为适当module变量的值。

有没有必要包装整个ajax电话在这里。

+0

哦,我觉得这看起来有点干净。 – Chev

0

试试这种方式,告诉我它是否有效!

for (var n = 0; n < modules.length; n++) { 
(function() { 
    var i = n; 
     var module = modules[i]; 

     // Get module HTML. 
     $.ajax({ 
      url: modulesUrl + module.name, 
      success: function (moduleHtml) { 

       // Append module HTML to appropriate element. 
       $('#' + module.column + 'Column').append(moduleHtml); 

       // Custom event to trigger the module to load its data. 
       var initializeModuleEvent = $.Event('initialize' + module.name); 
       initializeModuleEvent.firstLoad = true; 
       $(document).trigger(initializeModuleEvent); 

      } 
     }); 
    }()); 
} 
2

而不是使用for循环使用jQuery的每..这将解决这个问题的

var modules = [ 
    { name: 'ExchangeStatus', title: 'Exchange Status', column: 'left' }, 
    { name: 'Grid', title: 'Contacts', column: 'right' } 
    { name: 'Filters', title: 'Filters', column: 'left' } 
], 
modulesUrl = '/Modules/'; 

$(modules).each(function(index, elem) 
{ 
    var module = elem; 

    // Get module HTML. 
    $.ajax({ 
     url: modulesUrl + module.name, 
     success: function (moduleHtml) { 

      // Append module HTML to appropriate element. 
      $('#' + module.column + 'Column').append(moduleHtml); 

      // Custom event to trigger the module to load its data. 
      var initializeModuleEvent = $.Event('initialize' + module.name); 
      initializeModuleEvent.firstLoad = true; 
      $(document).trigger(initializeModuleEvent); 

     } 
    }); 
} 
} 
); 
+0

我过去遇到的唯一问题是jQuery的'each'也会迭代对象的属性。我曾经在服务器返回错误的地方出现了一个令人讨厌的错误,jQuery冻结了尝试迭代不应该重复的页面。因为它,我现在可能是偏执狂了,哈哈。 – Chev

相关问题