如何获取获取请求中的数据平均值?

时间:2018-04-05 11:47:57

标签: javascript function fetch es6-promise

所以我有一个填充了API数据的表。现在我想添加一个<p>标签,其中包含数据中的平均质量密钥。以下是我需要获取表格数据的代码: const url =&#39; https://swapi.co/api/species/1/&#39;;

  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;
    })
  )

);

当我运行此代码时,我收到此错误:

未捕获(承诺)TypeError:getMass.reduce不是fetchData.then.result中的函数

我可以以某种方式更改此内容以在此获取内部运行,还是必须具有单独的功能?

3 个答案:

答案 0 :(得分:2)

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

首先,你试图给每个人的质量打.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

如果您需要小数质量(如parseFloat),请使用parseInt代替"77.25"

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

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

这就是我的意思,希望这些评论可以帮助您了解详情:

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
})();
<p>average mass: <span id="sw-mass">…</span></p>

答案 1 :(得分:1)

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

&#13;
&#13;
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
  });
});
&#13;
Average mass: <span id="sw-mass">(calculating)</span>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

网址&#39; https://swapi.co/api/species/1/&#39;返回以下内容但没有质量属性。

{
"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/"   }   

网址&#39; https://swapi.co/api/people/1/?format=json&#39;确实有mass属性但不是数组,因此.reduce和.filter都不起作用,因为它们只是数组对象上存在的方法。