所以我有一个填充了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中的函数
我可以以某种方式更改此内容以在此获取内部运行,还是必须具有单独的功能?
答案 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
)才能计算平均值:
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;
答案 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都不起作用,因为它们只是数组对象上存在的方法。