如何使用Javascript/AJAX按特定顺序加载多个文件的内容
我使用JS/AJAX在一个页面上显示多个文件的内容。这些文件是动态生成的,并使用for循环加载。有一个文件包含集合的元数据,包括需要加载的其他文件的数量。其他文件的文件名中有一个数字,我通过请求“file_0;[loop_index].json”来加载它们 问题是,每个json文件中的数据量也是任意的,AJAX调用将以最小文件的顺序首先完成。我希望根据名称而不是大小按顺序显示数据 下面是一个简化的示例,假设我们要显示一本书的内容:如何使用Javascript/AJAX按特定顺序加载多个文件的内容,javascript,json,ajax,Javascript,Json,Ajax,我使用JS/AJAX在一个页面上显示多个文件的内容。这些文件是动态生成的,并使用for循环加载。有一个文件包含集合的元数据,包括需要加载的其他文件的数量。其他文件的文件名中有一个数字,我通过请求“file_0;[loop_index].json”来加载它们 问题是,每个json文件中的数据量也是任意的,AJAX调用将以最小文件的顺序首先完成。我希望根据名称而不是大小按顺序显示数据 下面是一个简化的示例,假设我们要显示一本书的内容: function get(url) { return new
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
}
else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
get('toc.json').then(function(response) {
chapters = JSON.parse(response)["chapters"];
return chapters;
}).then(function(levels) {
for (i = 0; i < chapters; i++) {
(function (i) {
get("chap".concat(i,".json")).then(function(response) {
console.log(response);
})
}(i));
}
});
第0.6章:
{ "text" : "00000" }
第1.1章:
{ "text" : "1" }
结果将是:
{ "text" : "1" }
{ "text" : "00000" }
如果我切换每个文件中的字符数,结果将是:
{ "text" : "0" }
{ "text" : "11111" }
我想打印在“1”行之前带有“0”的行,而不管每个文件大小
我不能使用async/await,因为我的页面必须在IE11中工作,并且它不支持箭头函数
我想到的解决方案是将内容存储在一个数组中,从for循环返回,然后显示内容,即:
尝试的解决方案:
var tempArray = [];
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
} else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
get('toc.json').then(function(response) {
chapters = JSON.parse(response)["chapters"];
return chapters;
}).then(function(levels) {
for (i = 0; i < chapters; i++) {
(function(i) {
get("chap".concat(i, ".json")).then(function(response) {
console.log(response);
tempArray[i] = response;
})
}(i));
}
return tempArray;
}).then(function(response) {
console.log(response);
}
);
我认为这是失败的,因为承诺序列在实际AJAX调用完成之前经过for循环部分。如果我能想出如何让它等待他们完成,我会在那里,但此刻我被难住了
另一种在其他情况下可以工作的解决方案是动态生成部分html,并用相应的文件内容更新正确的元素。不幸的是,对于我的特定用例,这不是一个选项
有什么帮助吗?谢谢你。竭尽全力使用承诺。为什么不将名称放在一个数组中,让一个函数执行获取、更新计数器并再次调用该函数
var listOfFiles=["fileList.txt”],
cnt=0,
oReq = new XMLHttpRequest();
function reqListener () {
if (listOfFiles[0]=="fileList.txt") {
listOfFiles = this.responseText.split(",");
}
else {
processFile(this.responseText);
cnt++;
}
getFile();
}
oReq.addEventListener("load", reqListener);
function getFile() {
if (cnt >= listOfFiles.length) return;
oReq.open("GET", listOfFiles[cnt]);
oReq.send();
}
getFile();
使用(从示例中删除XHR,但仍然使用承诺)
函数getTOC(){
var jsonStr=JSON.stringify({
第二章,
});
返回承诺。解决(jsonStr);
}
第(一)章的职能{
返还承诺。决议(“第“+i章”);
}
getTOC()
.然后(功能(响应){
var chapters=JSON.parse(响应)[“chapters”];
返回章节;
})
.然后(功能(章节){
var承诺=[];
对于(i=0;i<章节;i++){
承诺.推动(第一章);;
}
返回承诺。全部(承诺);
})
.然后(函数(结果){
//结果是一个结果数组,按预期顺序排列
控制台日志(结果);
});
如果确实需要按特定顺序加载,则不希望使用异步请求。改用同步请求@Mikefullender你真的在推荐同步AJAX吗?正如你链接到的那篇文章所提到的,由于它所带来的糟糕的用户体验,一些主要的浏览器已经弃用了它,所以它很有可能在将来被删除。该页面明确表示“建议开发人员远离API。”虽然没有提到Chrome,但他们也不赞成使用它。除了创建一个糟糕的用户体验,它也不能被依赖(中期)。@MikeFurlender我建议不要使用同步请求。这将使浏览器无响应。我没有意识到同步XMLHttpRequests正在阻塞。很高兴知道。在这种情况下,将order索引传递给ajax请求,并使用order索引作为键将响应写入对象。当所有的承诺都解决时,使用键组合对象中的值来强制执行顺序。我目前正在尝试调整这个答案,看看它是否适合我。主要问题是listOfFiles中的文件数量可能会改变,我目前正在使用AJAX调用在开始循环数据文件之前获取该列表。对于如何处理这个问题,你有什么建议吗?为了让它正常工作,我不得不对它进行更多的调整,特别是我不得不将“ListOfFiles”重命名为“fileList”,不确定这是否是你的意思。但一旦我明白了这一点,它确实解决了问题。这可能会奏效,除非我在发布这个问题后意识到承诺/承诺。所有这些都不受IE11的支持,我提到我需要能够运行IE11。
Array[]
var listOfFiles=["fileList.txt”],
cnt=0,
oReq = new XMLHttpRequest();
function reqListener () {
if (listOfFiles[0]=="fileList.txt") {
listOfFiles = this.responseText.split(",");
}
else {
processFile(this.responseText);
cnt++;
}
getFile();
}
oReq.addEventListener("load", reqListener);
function getFile() {
if (cnt >= listOfFiles.length) return;
oReq.open("GET", listOfFiles[cnt]);
oReq.send();
}
getFile();
function getTOC() {
var jsonStr = JSON.stringify({
chapters: 2,
});
return Promise.resolve(jsonStr);
}
function getChapter(i) {
return Promise.resolve("chapter " + i);
}
getTOC()
.then(function(response) {
var chapters = JSON.parse(response)["chapters"];
return chapters;
})
.then(function(chapters) {
var promises = [];
for (i = 0; i < chapters; i++) {
promises.push(getChapter(i));
}
return Promise.all(promises);
})
.then(function(results) {
// results is an array of results, ordered as expected
console.log(results);
});