我正在获取 JSON,它返回多个项目,所以我使用 For 循环来访问这些项目,在每个项目上,我需要获取另一个 json,但是它在循环完成时运行。请看下面的代码:
fetch(url).then(function(response){
response.json().then(function(data) {
//do something
for (item of data.list){ //list is the key of JSON returned
//do something
for (key in item){
if (key == "id"){
//do something
console.log(item.id);
} else {
//do something
console.log('other item key');
if (key == "name"){
fetch(url + '/' + item.id).then(function(response){
response.json().then(function(data) {
//do something
console.log('fetch item: ' + key);
});
});
} else if (key == "address"){
fetch(url + '/' + item.address).then(function(response){
response.json().then(function(data) {
//do something
console.log('fetch item: ' + key);
});
});
} else if (key == "city"){
fetch(url + '/' + item.city).then(function(response){
response.json().then(function(data) {
//do something
console.log('fetch item: ' + key);
});
});
}
}
}
}
console.log('loop end');
});
});
预期结果:0
other item key
fetch item: name
fetch item: address
fetch item: city
loop end
但我明白了0
other item key
loop end
fetch item: city
fetch item: city
fetch item: city
请帮忙!太感谢了。
最佳答案
如果我理解正确,您正在尝试在所有获取完成后执行某些操作。我最喜欢的方法是使用 Promises 和 async await 语法。我重写了你的代码,试图把事情弄平,现在它也会等到循环完成后再记录“循环结束”。
我做的第一件事是将我的整个操作包装在一个匿名异步函数中,该函数会立即被调用。
我之所以使用异步,是因为它需要使用等待。现在不再使用 .then
链,我可以告诉代码在继续之前等待获取完成。这不仅适用于返回 promise 的 fetch,而且适用于 .json
方法也返回一个 promise 。for of
循环与您的相似,但我使用 const
关键字以防止更改全局变量的值。
我假设总是有一个 id,并且会使用 id 操作而不需要检查是否有一个 id。
我没有遍历每个键并在找到某个键时执行代码的 if 语句,而是遍历所需的目标并在键不存在时跳过执行代码。
如果您需要为任何键做不同的事情,您可以将它们从循环中移除并重复它,但它会变得很湿。任何重复的东西都应该放在一个函数或循环中,只写一次
如果您有任何问题,请询问!
(async () => {
const response = await fetch(url);
const data = await response.json();
for (const item of data.list) {
//do something with id?
for (const key of ["name", "address", "city"]) {
if (!(key in item)) continue;
const keyRes = await fetch(`${url}/${item[key]}`);
const keyData = await keyRes.json();
//do something
console.log(`fetch item: ${key}`);
}
}
console.log("loop end");
})();
您提到提取发生的时间太长,为了给您一个示例,说明这样做没有阻塞循环,而是阻塞直到所有循环 promise 解决,这是另一个示例。这里我们写了一个异步函数
processKey
使用 async await 语法处理处理。异步函数总是返回一个promise,await 关键字将等待promise 解决。这样,我们可以调用该函数,但我们可以将 Promise 存储在一个数组中,而不是等待它解析。在我们启动所有 promise 而不等待它们解决之后,我们可以使用
await Promise.all(promisesToWaitFor)
并等到数组中的所有 promise 都解决后,再执行最后一行代码。应该指出的是,我们不再等待循环中的代码执行来节省时间。正因为如此,如果一次获取时间少于另一次,我们将在循环中发生“无序”的操作。根据您的用例,这可能是理想的,也可能不是理想的。
如果您需要任何代码说明,请询问!
async function processKey(key, url, item) {
const keyRes = await fetch(`${url}/${item[key]}`);
const keyData = await keyRes.json();
//do something
console.log(`fetch item: ${key}`);
}
const url = "Something";
(async () => {
const response = await fetch(url);
const data = await response.json();
const promisesToWaitFor = [];
for (const item of data.list) {
//do something with id?
for (const key of ["name", "address", "city"]) {
if (!(key in item)) continue;
const processPromise = processKey(key, url, item);
promisesToWaitFor.push(processPromise);
}
}
await Promise.all(promisesToWaitFor);
console.log("loop end");
})();
编辑:你提到你想让事情井井有条。我决定不要并排执行所有 Action ,而是可以存储所有
.json
promise 到一个数组中,然后在它们全部启动后,逐步遍历该数组,等待每个完成。这样可以保持事物的顺序,同时仍然可以获得更好的速度。我想澄清的一件事是将 async/await 与 Promise 链结合
.then
方法。我有线
const jsonPromise = fetch(`${url}/${item[key]}`).then(res => res.json());
这将使用 Promise 链在一行中触发获取和转换为 json 的操作。我可以将该 Promise 存储在一个变量中以转换为 json,然后将其存储在一个数组中。由于我们想要使用该数据执行的操作涉及用于获取数据的 key ,因此我将 promise 和 key 都传递给数组中的一个对象。在我们触发所有获取之后,我有一个单独的循环,它使用
await
等待操作完成。(async () => {
const response = await fetch(url);
const data = await response.json();
const fetchToWaitFor = [];
for (const item of data.list) {
//do something with id?
for (const key of ["name", "address", "city"]) {
if (!(key in item)) continue;
const jsonPromise = fetch(`${url}/${item[key]}`).then(res => res.json());
fetchToWaitFor.push({jsonPromise, key});
}
}
for (const waitObj of fetchToWaitFor) {
const {key, jsonPromise} = waitObj;
const data = await jsonPromise;
console.log(`fetch item: ${key}`);
}
console.log("loop end");
})();
关于javascript - 在循环完成后的 For 循环中获取 json JS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70254783/