我正在使用JS / AJAX在页面上显示多个文件的内容。这些文件是动态生成的,并使用for循环进行加载。有一个文件包含该集合的元数据,包括需要加载多少其他文件。其他文件的文件名中有一个数字,我通过请求“ file_ [loop_index] .json”来加载它们。
问题是,每个json文件中的数据量也是任意的,并且AJAX调用将首先以最小文件的顺序完成。我想按名称而不是大小顺序显示数据。
这是一个简化的示例,假设我们要显示一本书的内容:
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));
}
});
toc.json:
{ "chapters": 2 }
chap0.json:
{ "text" : "00000" }
chap1.json:
{ "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);
}
);
但是最终的console.log(response)产生:
Array[]
我想这失败了,因为在实际的AJAX调用完成之前,promise序列正在通过for循环部分。如果我能弄清楚如何等待他们完成任务,我会在那里,但此刻我很沮丧。
可以在其他情况下使用的另一种解决方案是动态生成html的一部分,并使用相应的文件内容更新正确的元素。不幸的是,对于我的特定用例,这不是一个选择。
有帮助吗?谢谢。
答案 0 :(得分:1)
弯腰使用诺言。为什么不只将名称包含在数组中,并让一个函数进行获取,更新计数器并再次调用该函数?
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();
答案 1 :(得分:1)
使用Promise.all
(示例中已删除XHR,但仍使用Promises)。
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);
});