我需要运行任意数量的脚本。下一个只能运行前一个已加载并执行的。我知道RequireJS(及相关)将是正确的选择,但我正在努力学习承诺,所以这是我的实验:
var files = [
'first.js',
'second.js',
'third.js',
'fourth.js'
];
var funcs = files.map(function(file) {
return function() { return $.getScript(file); }
});
var deferred = $.Deferred();
funcs.reduce(function (soFar, f) {
return soFar.then(f);
}, deferred.resolve(funcs[0]));
有人可以详细说明我的解决方案的缺陷和替代方案吗?
答案 0 :(得分:1)
你真正想要的是.pipe(或者1.8+,我相信。然后改为意思是同样的事情)
简而言之,管道将允许您以您正在寻找的方式链接承诺。代码可能看起来像这样(未经测试):
var files, scriptsLoaded;
files = [ 'first.js', 'second.js', 'third.js', 'fourth.js' ];
while( files.length ) {
(function() {
var currentUrl = files.shift();
scriptsLoaded = scriptsLoaded ?
scriptsLoaded.pipe(function() {
return $.getScript( currentUrl );
}) :
$.getScript( currentUrl );
}());
}
$.when( scriptsLoaded ).done(function() {
// All scripts are now loaded assuming none of them failed
});
**编辑**
通过您提供的链接,我了解您要完成的任务。以下是您的解决方案的更正版本以及一些注释。它完成了与其他解决方案相同的功能,但它是一个更简洁的版本:
var files = [ 'first.js', 'second.js', 'third.js', 'fourth.js' ];
// The initial value provided to the reduce function is a promise
// that will resolve when the first file has been loaded. For each
// of the remaining file names in the array, pipe it through that first
// promise so that the files are loaded in sequence ( chained ).
// The value that is returned from the reduce function is a promise
// that will resolve only when the entire chain is done loading.
var scriptsLoaded = files.slice(1).reduce(function (soFar, file) {
return soFar.pipe(function() {
return $.getScript( file );
});
}, $.getScript( files[0] );