【问题标题】:How do I the average of data inside of a fetch request?如何平均获取请求中的数据?
【发布时间】:2018-04-05 21:53:32
【问题描述】:

所以我有一个表格,其中填充了来自 API 的数据。现在我想添加一个<p> 标记,其中包含数据中的平均质量键。这是我必须获得效果很好的表数据的代码: const url = 'https://swapi.co/api/species/1/';

  function fetchData(url) {
     return fetch(url).then((resp) => resp.json());
  }


    function constructTableRow(data) {
      const row = document.createElement('tr');
      const { name, height, mass, hair_color } = data;
      row.appendChild(constructElement('td', name))
      row.appendChild(constructElement('td', height))
      row.appendChild(constructElement('td', mass))
      row.appendChild(constructElement('td', hair_color))
      return row;
   }

const swTable = document.getElementById('sw-table').getElementsByTagName('tbody')[0];
fetchData(url).then(data =>
data.people.forEach(personUrl =>
    fetchData(personUrl).then(result => {
      const row = constructTableRow(result);
      swTable.appendChild(row);
   })
 )
);

现在这是我必须得到平均值的代码,但它不起作用:

const link = 'https://swapi.co/api/species/1/';
 function fetchLink(link) {
   return fetch(link).then((resp) => resp.json());
 }

 fetchLink(link).then(data =>
    data.people.forEach(personUrl =>
    fetchData(personUrl).then(result => {
      const getMass = result.mass;
         return getMass.reduce(function(a, b) {
            return a + b;
        }) / getMass.length;
    })
  )

);

当我运行这段代码时,我得到了这个错误:

Uncaught (in promise) TypeError: getMass.reduce is not a function at fetchData.then.result

我可以以某种方式改变它以在这个 fetch 内部运行还是我必须有一个单独的函数?

【问题讨论】:

  • getnMass 拼写错误
  • @nirus 谢谢,但它仍然给出同样的错误。
  • 你确定响应数据是 json,如果我只是在浏览器中输入 url,我会得到一个 HTML 页面,而不仅仅是 .json
  • fetchData 函数长什么样?此外,您的数据源中的某些人拥有mass: "unknown",您可能希望将其过滤掉。
  • @SebastianSpeitel 它从 swapi.co/api/people/1/?format=json 解析

标签: javascript function fetch es6-promise


【解决方案1】:

您的代码中几乎没有未处理的问题。

首先,您尝试在每个人的质量上调用.reduce,这没有什么意义:

const getMass = result.mass;
return getMass.reduce(function(a, b) {
  return a + b;
}) / getMass.length;

这是您的 getMass.reduce is not a function 错误的来源——.reduce 方法适用于数组,并且 result.mass 是,例如"77",所以上面没有.reduce

其次,这个人的质量不是一个数字,它实际上是一个字符串("77",不是77),所以即使是这些质量的数组(["87", "77", …])也不会得到总和和平均质量:

["87", "77"].reduce((a, sum) => a + sum) // -> "8777"

您必须先将这些转换为实际数字:

["87", "77"].map(a => parseInt(a)) // -> [87, 77]
[87, 77].reduce((a, sum) => a + sum) // -> 164

如果您期望小数质量(如"77.25"),请使用parseFloat 而不是parseInt

此外,其中一些字符串甚至不是数字,而是"unknown"。所以你必须过滤掉它们:

["87", "77", "unknown"].filter(mass => !isNaN(mass)) // -> ["87", "77"]

这就是我的处理方式,希望cmets可以帮助您详细说明:

const getAvgMass = async url =>
  fetch(url)
    .then(r => r.json())
    .then(
      async data =>
        (await Promise.all( // return the array after all persons are fetched and processed
          data.people.map(personUrl => // take each person's URL,
              fetch(personUrl) // fetch the data from it,
                .then(r => r.json())
                // and replace the URL in an array with person's mass
                // (parseInt parses numeral strings like "77" to 77 (integer),
                // and non-numeral strings like "unknown" to NaN):
                .then(person => parseInt(person.mass)) // => [77, 136, 49, 120, 75, 84, 77, 84, NaN, 80, 77, NaN, …]
          )
        // filter out these NaNs:
        )).filter(mass => !isNaN(mass)) // -> [77, 136, 49, 120, 75, 84, 77, 84, 80, 77, …]
    )
    // sum all masses and divide it by (filtered) array length:
    .then(masses => masses.reduce((sum, x) => sum + x) / masses.length); // -> 82.77272…


// top-level await is not (yet? https://github.com/MylesBorins/proposal-top-level-await) supported
// in browsers (except Chrome console in recent versions), so to log the result, we have to do:
// getAvgMass("https://swapi.co/api/species/1/").then(result => console.log(result)); // logs 82.77272…

// or:
// const logResult = async () => console.log(await getAvgMass("https://swapi.co/api/species/1/"));
// logResult(); // logs 82.77272…

// or even:
// (async () => {
//   console.log(await getAvgMass("https://swapi.co/api/species/1/")) // logs 82.77272…
// })();

// to use in a DOM element, just replace console.log:

(async () => {
  const avgMass = await getAvgMass("https://swapi.co/api/species/1/");
  console.log(avgMass); // logs 82.77272…
  document.getElementById("sw-mass").innerText = avgMass.toFixed(2); // sets the <span> text to 82.77
})();
&lt;p&gt;average mass: &lt;span id="sw-mass"&gt;…&lt;/span&gt;&lt;/p&gt;

【讨论】:

  • 你可以对结果做任何你想做的事情,我会把它添加到示例 sn-p
  • 没关系,我让它工作了。我做到了,错误非常感谢
  • 很高兴它有帮助。无论如何它都在 sn-p 中 - 基本上你只需等待结果(使用 async/await.then(…)然后用它做一些事情(将它记录到控制台或在元素中使用它或......) .
【解决方案2】:

您的每个质量值都在不同的 JSON 调用中,因此您必须等待所有提取完成(使用 Promise.all)才能计算平均值:

const link = 'https://swapi.co/api/species/1/';

function fetchLink(link) {
  return fetch(link).then((resp) => resp.json());
}

fetchLink(link).then(data => {
  Promise.all(data.people.map(url => { // get all the urls
    return fetchLink(url);
  })).then(responses => {
    const masses = responses.map(resp => resp.mass) // get just the mass from each
      .filter(m => {
        return m !== 'unknown' // drop the "unknown" masses from the array
      });

    const average = masses
      .map(x => x / masses.length)
      .reduce((adder, value) => (adder + value))
      .toFixed(2);
    document.getElementById('sw-mass').innerHTML = average;
    return average
  });
});
Average mass: &lt;span id="sw-mass"&gt;(calculating)&lt;/span&gt;

【讨论】:

    【解决方案3】:

    url 'https://swapi.co/api/species/1/' 返回以下内容,但没有质量属性。

    {
    "name": "Human", 
    "classification": "mammal", 
    "designation": "sentient", 
    "average_height": "180", 
    "skin_colors": "caucasian, black, asian, hispanic", 
    "hair_colors": "blonde, brown, black, red", 
    "eye_colors": "brown, blue, green, hazel, grey, amber", 
    "average_lifespan": "120", 
    "homeworld": "https://swapi.co/api/planets/9/", 
    "language": "Galactic Basic", 
    "people": [
        "https://swapi.co/api/people/1/", 
        "https://swapi.co/api/people/4/", 
        "https://swapi.co/api/people/5/", 
        "https://swapi.co/api/people/6/", 
        "https://swapi.co/api/people/7/", 
        "https://swapi.co/api/people/9/", 
        "https://swapi.co/api/people/10/", 
        "https://swapi.co/api/people/11/", 
        "https://swapi.co/api/people/12/", 
        "https://swapi.co/api/people/14/", 
        "https://swapi.co/api/people/18/", 
        "https://swapi.co/api/people/19/", 
        "https://swapi.co/api/people/21/", 
        "https://swapi.co/api/people/22/", 
        "https://swapi.co/api/people/25/", 
        "https://swapi.co/api/people/26/", 
        "https://swapi.co/api/people/28/", 
        "https://swapi.co/api/people/29/", 
        "https://swapi.co/api/people/32/", 
        "https://swapi.co/api/people/34/", 
        "https://swapi.co/api/people/43/", 
        "https://swapi.co/api/people/51/", 
        "https://swapi.co/api/people/60/", 
        "https://swapi.co/api/people/61/", 
        "https://swapi.co/api/people/62/", 
        "https://swapi.co/api/people/66/", 
        "https://swapi.co/api/people/67/", 
        "https://swapi.co/api/people/68/", 
        "https://swapi.co/api/people/69/", 
        "https://swapi.co/api/people/74/", 
        "https://swapi.co/api/people/81/", 
        "https://swapi.co/api/people/84/", 
        "https://swapi.co/api/people/85/", 
        "https://swapi.co/api/people/86/", 
        "https://swapi.co/api/people/35/"
    ], 
    "films": [
        "https://swapi.co/api/films/2/", 
        "https://swapi.co/api/films/7/", 
        "https://swapi.co/api/films/5/", 
        "https://swapi.co/api/films/4/", 
        "https://swapi.co/api/films/6/", 
        "https://swapi.co/api/films/3/", 
        "https://swapi.co/api/films/1/"
    ], 
    "created": "2014-12-10T13:52:11.567000Z", 
    "edited": "2015-04-17T06:59:55.850671Z", 
    "url": "https://swapi.co/api/species/1/"   }   
    

    url 'https://swapi.co/api/people/1/?format=json' 确实具有质量属性,但不是数组,因此 .reduce 和 .filter 都不起作用,因为它们只是存在于数组对象上的方法。

    【讨论】:

    • 我能够获得相同的 url 来处理同一个 js 文件中的先前 fetchData。我将编辑我的问题以包含它,以便您了解我的意思
    • 检查我修改后的问题,了解我发布的代码之前的代码。
    猜你喜欢
    • 2014-02-26
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-28
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    相关资源
    最近更新 更多