我有一个简单的函数来提取模板数组:
function getTemplates(names,done,templates,index) { if (!index) index = 0; if (!templates) templates = {}; if (index === names.length) return done(templates); $.ajax({ url: '/templates/' + names[index] + '.min.html',success: function (data,status,xhr) { templates[names[index++]] = data; return getTemplates(names,index); } }); }
从一个到另一个,直到它们全部被检索,然后回调到调用函数,我似乎合乎逻辑.但我很好奇,如果这样做有任何不良副作用.到目前为止我还没有看到任何东西,但是我不想在没有首先了解任何潜在问题的情况下进行生产.
更新:
在Google和BenjaminGruenbaum的帮助下,我设计了一个解决方案:
function getTemplatesAsync(names,done) { var calls = []; var templates = {}; names.forEach(function (name,index) { calls.push( $.ajax({ url: '/templates/' + names[index] + '.min.html',xhr) { templates[names[index++]] = data; } }) ); }); $.when.apply($,calls).done(function () { // using "templates" here feels fragile for some reason. Am I wrong? return done(templates); }); }
我在这里使用模板因为我需要能够按名称引用每个模板,但不知何故它感觉很脆弱或不可靠.这看起来像一个安全的事情吗?
解决方法
您的更新代码比最初的代码要好得多,但它仍有一些问题,主要是混合承诺和回调,而不是使用语言功能(返回值)而不使用映射.
一些改进可以是:
>返回promise而不是回调参数
>使用.map而不是forEach with push.
>使用.then而不是成功回调来避免同一事物的两个处理程序和可能未指定的行为(何时首先执行?是否成功:?)
我们可以这样做:
function getTemplatesAsync(names) { return $.when.apply(null,names.map(function (name,index) { return $.get('/templates/' + names[index] + '.min.html'); }).then(function(results){ // map arguments to names return Array.prototype.reduce.call(arguments,function(obj,cur,idx){ obj[names[idx]] = cur; return obj; },{}); }); }
这可以让你做到:
getTemplatesAsync(names).then(function(templates){ // access templates here });