【问题标题】:Javascript Fetch inside a map地图内的Javascript Fetch
【发布时间】:2020-11-02 06:12:48
【问题描述】:

我有一个网站/作品集,我在其中使用 Github API 显示我的所有项目。我的目标是为这些项目创建一个过滤器,因此我在一些存储库的根目录中创建了一个名为“built-with.json”的文件,该文件存在于仅两个存储库中,仅用于测试目的,那是我在项目中使用的一系列技术(例如:[“React”,“Javascript”,...])。所以我需要获取 Github APi(它运行良好的那部分),然后获取该文件,并返回一个新的项目数组,但使用“filters”键,其中值是“built-with.json”中的数组.示例:

Github API 返回(仅返回一个项目的示例):

[{
"id": 307774617,
"node_id": "MDEwOlJlcG9zaXRvcnkzMDc3NzQ2MTc=",
"name": "vanilla-javascript-utility-functions",
"full_name": "RodrigoWebDev/vanilla-javascript-utility-functions",
"private": false
}]

我需要的新对象数组:

[{
"id": 307774617,
"node_id": "MDEwOlJlcG9zaXRvcnkzMDc3NzQ2MTc=",
"name": "vanilla-javascript-utility-functions",
"full_name": "RodrigoWebDev/vanilla-javascript-utility-functions",
"private": false,
"filters": ["HTML5", "CSS3", "JS", "React"]
}]

这就是我所做的:

const url = "https://api.github.com/users/RodrigoWebDev/repos?per_page=100&sort=created";
fetch(url)
  .then((response) => response.json())
  .then((data) => {
      return data.map(item => {
        //item.full_name returns the repositorie name
        fetch(`https://raw.githubusercontent.com/${item.full_name}/master/built-with.json`)
          .then(data => {
            item["filters"] = data
            return item
          })
      })
    })
  .then(data => console.log(data))

但它不起作用!我在控制台中得到了这个:

有人可以帮助我吗?提前致谢

注意:抱歉,如果您发现一些语法错误,我的英语正在开发中

【问题讨论】:

  • 这里有几件事。您不需要将.then() 链接到fetch()fetch() 返回一个承诺。 Array.prototype.map() 返回一个数组。放在一起,你最终会得到一系列的承诺。您可以使用 Promise.all(arrayOfPs) 解决一系列承诺
  • 您需要链接promise.all。请看this
  • 你在内部fetch('https://raw.githubusercontent…之前错过了一个return

标签: javascript arrays fetch github-api fetch-api


【解决方案1】:

这里有几件事。您不需要将 .then() 链接到 fetch()。 fetch() 返回一个承诺。 Array.prototype.map() 返回一个数组。放在一起,你最终会得到一系列的承诺。您可以使用 Promise.all(arrayOfPs)

解析承诺数组

编辑:在您的 cmets 并查看您的问题之后,我重写了它,以便它从过滤的存储库列表中检索技能。

const url = `https://api.github.com/users/RodrigoWebDev/repos?per_page=100&sort=created`;

(async() => {
  // Final results 
  let results;
  try {
    // Get all repositories
    const repos = await fetch(url).then((res) => res.json());
    const responses = await Promise.all(
      // Request file named 'build-with.json' from each repository
      repos.map((item) => {
        return fetch(
          `https://raw.githubusercontent.com/${item.full_name}/master/built-with.json`
        );
      })
    );
    // Filter out all non-200 http response codes (essentially 404 errors)
    const filteredResponses = responses.filter((res) => res.status === 200);
    results = Promise.all(
      // Get the project name from the URL and skills from the file
      filteredResponses.map(async(fr) => {
        const project = fr.url.match(/(RodrigoWebDev)\/(\S+)(?=\/master)/)[2];
        const skills = await fr.json();
        return {
          project: project,
          skills: skills
        };
      })
    );
  } catch (err) {
    console.log("Error: ", err);
  }
  results.then((s) => console.log(s));
})();

【讨论】:

  • 您的示例正在返回一个新的承诺数组,我需要一个带有关键“过滤器”的新 github 项目数组,我如何达到这个结果?
  • 该示例返回一个 HTTP 响应数组。它们都是404错误。我不认为我理解您的意思或您在结果中看到的内容。
  • 我重新阅读了您的问题。您无法通过“过滤器”确定哪些存储库具有此魔术文件。提供一个包含该文件的存储库,我将检索它并打印它的内容。
  • @Rodrigo - 你去吧!
【解决方案2】:

问题是 fetch 没有被返回,因此 .map() 返回未定义。我可以建议使用 async-await 的解决方案吗?

const url = "https://api.github.com/users/RodrigoWebDev/repos?per_page=100&sort=created";

getData(url).then(data => console.log(data));
  
async function getData(url){
  const response = await fetch(url);
  const data = await response.json();
  const arrOfPromises = data.map(item => fetch(`https://raw.githubusercontent.com/${item.full_name}/master/built-with.json`)
  );
  return Promise.all(arrOfPromises);
}

【讨论】:

  • 你甚至没有改变我的变量名 :-) LOL
  • 对不起,我确实使用了您的示例作为参考。我也赞成你的答案,因为它是正确的。如果这对您有问题,我将删除此答案。 @RandyCasburn
  • NO - 不要删除你的答案!它和我的一样有效。我只是在逗你。
  • 您的示例正在返回一个新的承诺数组,我需要一个带有关键“过滤器”的新 github 项目数组,我如何达到这个结果?
【解决方案3】:

你有多个问题:

  1. 在 map 函数内部不返回任何结果
  2. map 函数的结果实际上是另一个 Promise(因为 fetch 内部)。

那么你需要做什么:

  1. 从地图返回承诺 - 因此您将拥有一系列承诺
  2. 使用 Promise.all 等待第 1 点的所有承诺

类似这样的:



    var url1 = "https://api.github.com/users/RodrigoWebDev/repos?per_page=100&sort=created";
    var datum = fetch(url1)
      .then((response) => response.json())
      .then((data) => {
          return Promise.all(data.map(item => {
            //item.full_name returns the repositorie name
            return fetch(`https://raw.githubusercontent.com/${item.full_name}/master/built-with.json`)
              .then(data => {
                item["filters"] = data
                return item
              })
          }));
        }).then(data => console.log(data))

【讨论】:

  • 嘿尼基蒂亚。它起作用了,但是返回的新对象数组不是过滤器数组,而是 fetch 的返回,请参阅ibb.co/t4Y04gQ。我尝试像这样ibb.co/VV0XT00 将响应传递给 json,但它不起作用
  • 要了解那里发生了什么,我需要看看你收到了什么,你可以尝试 .text() 而不是 .json() - 也许它会给你一个线索
  • 使用 .text() 它可以工作,但是它返回了一个字符串(jsfiddle.net/gtqjna1y 检查返回数组中的“my-website”存储库),我可以将字符串更改为一个数组,但是有什么方法可以将它作为一个数组?为了您更好地理解,我要获取两个带有“built-with.json”文件的存储库,这些存储库是 my-website 和 border-radius-previewer,如果可以使其适用于这两个,我将创建每个项目中的 thie 文件来构建我的过滤器
  • 我需要看看你从网络收到了什么,可能是 json 在那里被字符串化或类似的东西,你可以在 text() 上尝试 JSON.parse 看看是否有效
  • 请检查这个网址:jsfiddle.net/gtqjna1y,在开发工具控制台中检查返回数组中的“my-website”存储库,我收到的是什么,或者你可以看到这个截图ibb.co/t4Y04gQ。 JSON.parse 不起作用,因为响应不是 JSON 字符串化而是 promise 对象
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
  • 1970-01-01
  • 2016-11-01
  • 1970-01-01
  • 2022-01-14
  • 2017-04-20
相关资源
最近更新 更多