我有一个index.json
文件,它返回需要加载的其他N
个JSON文件的列表。它们需要使用不同的方法加载,这样当它们全部加载时,我可以一次处理它们。
服务器上可能存在或不存在其他每个JSON文件。
我正在使用以下方法加载数据,当服务器上实际存在所有文件时,该方法正常工作:
$.getJSON('index.json').then(function (response) {
var files = response.files;
$.when
.apply(null, getDeferreds(files))
.done(function() {
//process the files
})
});
});
function getDeferreds(files) {
var deferreds = [], i;
for (i in files) {
//file type 1
deferreds.push(
$.getJSON(files[i] + '_1.json')
.then(function (response) {
//do something
})
);
//file type 2
deferreds.push(
$.getJSON(files[i] + '_2.json')
.then(function (response) {
//do something
})
);
}
return deferreds;
};
这种方法很有效,但是......
当缺少任何文件时,即somefile_2.json
(有时在文件实际存在于服务器之前将创建索引),整个过程失败,并且没有任何数据被检索。
在$.getJson (
或$.get
内,我可以使用.fail()
方法检测到错误,但这并不能阻止呼叫失败,.done()
永远不会被召唤。
即使缺少某些文件,我如何重构此方法以使.done()
方法始终有效?
答案 0 :(得分:1)
事实证明解决方案比我想象的更简单。
我的猜测是,当调用失败时,在某个过程中,延迟对象无法正确解析。
只需将return $.Deferred().resolve();
添加到失败回调即可。
发布一个包含错误处理的完整解决方案,以防有人帮助:
$.getJSON('index.json').then(function (response) {
var files = response.files;
$.when
.apply(null, getDeferreds(files))
.done(function() {
//process the files
})
});
});
function getDeferreds(files) {
var deferreds = [], i;
for (i in files) {
deferreds.push(
$.getJSON(files[i])
.then(function (response) {
//do something
}, function() {
return $.Deferred().resolve([]);
})
);
};
return deferreds;
};
答案 1 :(得分:0)
你写的内容看起来不错,前提是do something
包含一个return语句,用于在promise链中(在调用者中)进一步传递数据。
你可能会考虑一些整理,并且"切蛋糕"不同的是,通过:
这是一个偏好问题,但我可能会选择写:
$.getJSON('index.json').then(function (response) {
return getFileData(response.files);
}).then(function(dataArray) {
// `dataArray` is an array of data items
// Do all processing here
});
});
function getFileData(files) {
var promises = files.map(function(file) {
return $.getJSON(file)
.then(null, // No processing here
function() {
return $.when([]); // $.when(value) is a useful shorthand for $.Deferred().resolve(value)
});
});
// By aggregating the promises here, caller(s) can be delivered an array of data items, wrapped in a single promise.
return $.when.apply(null, promises).then(function() {
return Array.prototype.slice.call(arguments); //convert function's `arguments` to a proper array
});
};
当然,如果getFileData()
不会从其他地方调用,您可以在调用者中执行所有操作。