Nutritionix API部分营养值返回NaN错误的排查请求
我写了个调用Nutritionix API获取食物营养数据的脚本,部分营养值能正常返回,但剩下的全是NaN。我怀疑要么是API免费版权限不够,要么是代码里的字段ID(比如nf_biotin、nf_iron这类)写错了。
let table = base.getTable('Raw Meals 2') let {records} = await table.selectRecordsAsync() console.log(records) for (let record of records){ const url = 'https://trackapi.nutritionix.com/v2/natural/nutrients'; const options = { method: 'POST', headers: { 'Content-type' : 'application/json', 'x-app-key':'--', 'x-app-id': '--' }, body: JSON.stringify({ 'query':`${record.name}` }) } let Response = await fetch (url,options); let data = await Response.json(); //WORKING const calories = data.foods.reduce((acc, item) => acc + item.nf_calories, 0) const protein = data.foods.reduce((acc, item) => acc + item.nf_protein, 0) const carbs = data.foods.reduce((acc, item) => acc + item.nf_total_carbohydrate, 0) const fat = data.foods.reduce((acc, item) => acc + item.nf_total_fat, 0) const saturatedfat = data.foods.reduce((acc, item) => acc + item.nf_saturated_fat, 0) const sugars = data.foods.reduce((acc, item) => acc + item.nf_sugars, 0) const cholesterol = data.foods.reduce((acc, item) => acc + item.nf_cholesterol, 0) const fiber = data.foods.reduce((acc, item) => acc + item.nf_dietary_fiber, 0) const potassium = data.foods.reduce((acc, item) => acc + item.nf_potassium, 0) const sodium = data.foods.reduce((acc, item) => acc + item.nf_sodium, 0) //NOT WORKING (NaN) const addsugars = data.foods.reduce((acc, item) => acc + item.nf_added_sugars, 0) const vita = data.foods.reduce((acc, item) => acc + item.nf_vitamin_a, 0) const vitb1 = data.foods.reduce((acc, item) => acc + item.nf_thiamin, 0) const vitb2 = data.foods.reduce((acc, item) => acc + item.nf_riboflavin, 0) const vitb3 = data.foods.reduce((acc, item) => acc + item.nf_niacin, 0) const vitb5 = data.foods.reduce((acc, item) => acc + item.nf_panthothenic_acid, 0) const vitb6 = data.foods.reduce((acc, item) => acc + item.nf_vitamin_b6, 0) const vitb7 = data.foods.reduce((acc, item) => acc + item.nf_biotin, 0) const vitb9 = data.foods.reduce((acc, item) => acc + item.nf_folate, 0) const vitb12 = data.foods.reduce((acc, item) => acc + item.nf_vitamin_b12, 0) const vitc = data.foods.reduce((acc, item) => acc + item.nf_vitamin_c, 0) const vitd = data.foods.reduce((acc, item) => acc + item.nf_vitamin_d, 0) const vite = data.foods.reduce((acc, item) => acc + item.nf_vitamin_e, 0) const vitk = data.foods.reduce((acc, item) => acc + item.nf_vitamin_k, 0) const transfat = data.foods.reduce((acc, item) => acc + item.nf_trans_fat, 0) const monofat = data.foods.reduce((acc, item) => acc + item.nf_monounsaturated_fat, 0) const polyfat = data.foods.reduce((acc, item) => acc + item.nf_polyunsaturated_fat, 0) const ftype = data.foods.reduce((acc, item) => acc + item.food_type, 0) const fcateg = data.foods.reduce((acc, item) => acc + item.food_category, 0) const calcium = data.foods.reduce((acc, item) => acc + item.nf_calcium, 0) const iron = data.foods.reduce((acc, item) => acc + item.nf_iron, 0) const selenium = data.foods.reduce((acc, item) => acc + item.nf_selenium, 0) const zinc = data.foods.reduce((acc, item) => acc + item.nf_zinc, 0) const magnesium = data.foods.reduce((acc, item) => acc + item.nf_magnesium, 0) const phosphorus = data.foods.reduce((acc, item) => acc + item.nf_phosphorus, 0) const omega3 = data.foods.reduce((acc, item) => acc + item.nf_omega_3_total, 0) const omega6 = data.foods.reduce((acc, item) => acc + item.nf_omega_6_total, 0) const aminos = data.foods.reduce((acc, item) => acc + item.nf_amino_acids, 0) const lysine = data.foods.reduce((acc, item) => acc + item.nf_lysin, 0) const leucine = data.foods.reduce((acc, item) => acc + item.nf_leucine, 0) const isoleucine = data.foods.reduce((acc, item) => acc + item.nf_isoleucine, 0) const valine = data.foods.reduce((acc, item) => acc + item.nf_valine, 0) const threonine = data.foods.reduce((acc, item) => acc + item.nf_threonine, 0) const phenylalanine = data.foods.reduce((acc, item) => acc + item.nf_phenylalanine, 0) const methionine = data.foods.reduce((acc, item) => acc + item.nf_methionine, 0) const histidine = data.foods.reduce((acc, item) => acc + item.nf_histidine, 0) const tryptophan = data.foods.reduce((acc, item) => acc + item.nf_tryptophan, 0) const betacarotene = data.foods.reduce((acc, item) => acc + item.nf_beta_carotene, 0) const lycopene = data.foods.reduce((acc, item) => acc + item.nf_lycopene, 0) const lutein = data.foods.reduce((acc, item) => acc + item.nf_lutein, 0) const zeaxanthin = data.foods.reduce((acc, item) => acc + item.nf_zeaxanthin, 0) const flavonoids = data.foods.reduce((acc, item) => acc + item.nf_flavonoids, 0) const polyphenols = data.foods.reduce((acc, item) => acc + item.nf_polyphenols, 0) const caffeine = data.foods.reduce((acc, item) => acc + item.nf_caffeine, 0) const alcohol = data.foods.reduce((acc, item) => acc + item.nf_alcohol, 0) const gi = data.foods.reduce((acc, item) => acc + item.nf_glycemic_index, 0) await table.updateRecordAsync(record, { 'Calories' : calories, 'Protein' : protein, 'Total Carbohydrate' : carbs, 'Total Fat' : fat, 'Saturated Fat' : saturatedfat, 'Dietary Fiber' : fiber, 'Cholesterol' : cholesterol, 'Sodium' : sodium, 'Potassium' : potassium, 'Sugars' : sugars }) }
让脚本里//NOT WORKING区域的所有营养值都能拿到API返回的真实数值,别再显示NaN。
核对API返回字段名
NaN大多是因为字段不存在导致的——访问不存在的对象属性会得到undefined,和数字相加就会变成NaN。在let data = await Response.json();后加console.log(data.foods[0]);,打印单条食物的完整返回数据,对比你用的字段名是否和实际一致。比如你写的nf_lysin,API实际可能是nf_lysine。给缺失字段加默认值
就算字段名正确,部分食物可能没有某些营养数据,API会直接不返回该字段。修改reduce逻辑,给缺失字段设默认值0:const addsugars = data.foods.reduce((acc, item) => acc + (item.nf_added_sugars || 0), 0);所有
NOT WORKING区域的reduce都要这么改,避免undefined参与运算。确认免费版API权限
Nutritionix免费版确实会限制部分营养数据,比如部分维生素、矿物质、进阶营养指标可能只有付费版能获取。核对官方的免费版字段列表,确认你要的指标是否在免费权限内。修复字符串累加错误
ftype和fcateg是字符串类型,用数字初始值累加会得到混乱结果,改成收集为字符串列表:const ftype = data.foods.map(item => item.food_type).join(', '); const fcateg = data.foods.map(item => item.food_category).join(', ');批量优化reduce逻辑
重复写reduce太繁琐,封装一个通用求和函数:function sumNutrient(foods, key) { return foods.reduce((acc, item) => acc + (item[key] || 0), 0); }调用时直接写
const vita = sumNutrient(data.foods, 'nf_vitamin_a');,简洁又减少出错概率。
内容的提问来源于stack exchange,提问作者reide

