javascript - 在循环完成后的 For 循环中获取 json JS

标签 javascript

我正在获取 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/

相关文章:

javascript - 如何正确使用 css @keyframes 和动画进行下拉菜单

javascript - 如何输入文本并使用 angularjs 呈现 html?

javascript - HTML Canvas 在其他电脑上的 Chrome 上无法正确调整大小

javascript - 使用 javascript 淡入/淡出和创建/隐藏 <DIV>

javascript - 如何将浏览器用作离线应用程序的 GUI?

javascript - 通过 POST 调用 Rails 函数

javascript - 使 v 菜单标题固定在顶部

javascript - 附加元素应保持悬停状态并离开休假

javascript - *在* JSON 完成后返回数组?

javascript - 无法获取要在 onClick 函数内执行的 if 语句