2

我写了一些javascript来运行一系列“模块”。对于每个模块,它都会进行 ajax 调用,获取模块的 html,并将模块转储到页面布局的两列之一中。

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 回调返回之前很久就完成了。如何维护模块变量,以便每个回调处理适当的模块?目前所有三个模块都在左列中,因为循环中的最后一个模块在左列中。

4

5 回答 5

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
});
于 2013-01-31T23:08:15.953 回答
2

将您的成功回调修改为:

$.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这里包装整个通话。

于 2013-01-31T23:09:15.467 回答
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);

        }
    });
}
}
);
于 2013-01-31T23:29:09.003 回答
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)
}
于 2013-01-31T23:08:39.160 回答
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);

            }
        });
    } ());
}
于 2013-01-31T23:17:54.397 回答