英文:
Why is an API response.json array not iterable in Svelte?
问题
I've been working on a simple nutrition tracking app as a final project for CS50, using Svelte and Firebase to make it fully functional. I've run into a problem in the frontend, as I'm using API calls to retrieve nutrition information. The API returns a json array which I would use to present options to the user and log information as they select. However, when I try to iterate over this array to make an option for each, I receive an error stating that it is not an array-type object.
I decided to reproduce the code in REPL, and achieved good results. The below code logs the full 50 items as an array, as per the API's documentation.
import { onMount } from 'svelte';
let foodList;
async function loadList() {
    let list = await fetch('https://api.nal.usda.gov/fdc/v1/foods/list?dataType=Foundation&api_key=DEMO_KEY');
    let foodList = await list.json();
    console.log(foodList);
}
onMount(() => {
    loadList();
});
I receive this abbreviated output:
(50) [ {…} ,{…} ,{…} ,{…} ,{…} , … ]
However, when trying to iterate over this array, I receive the error:
{#each} only iterates over array-like objects.
using below code:
{#await loadList}
    <p>
        Loading...
    </p>
{:then foodList}
    {#each foodList as item}
        <p>
            {item.description}
        </p>
    {/each}
{:catch error}
    <p style="color: red">{error.message}</p>
{/await}
I would appreciate any help, as I feel like I'm missing something fundamental that might be obvious to some others.
英文:
I've been working on a simple nutrition tracking app as a final project for CS50, using Svelte and Firebase to make it fully functional. I've run into a problem in the frontend, as I'm using API calls to retrieve nutrition information. The API returns a json array which I would use to present options to the user and log information as they select. However, when I try to iterate over this array to make an option for each, I receive an error stating that it is not an array-type object.
I decided to reproduce the code in REPL, and achieved good results. The below code logs the full 50 items as an array, as per the API's documentation.
import { onMount } from 'svelte';
	
    let foodList;
    async function loadList() {
        let list = await fetch('https://api.nal.usda.gov/fdc/v1/foods/list?dataType=Foundation&api_key=DEMO_KEY');
        let foodList = await list.json();
        console.log(foodList);
    }
		
    onMount(() => {
	loadList();
    });	
I receive this abbreviated output:
(50) [ {…} ,{…} ,{…} ,{…} ,{…} , … ]
However, when trying to iterate over this array, I receive the error:
{#each} only iterates over array-like objects.
using below code:
{#await loadList}
	<p>
		Loading...
</p>
{:then foodList}
	{#each foodList as item}
		<p>
			{item.description}
	</p>
	{/each}
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}
I would appreciate any help, as I feel like I'm missing something fundamental that might be obvious to some others.
答案1
得分: 0
Your #await is trying to check the function, not a promise.
Could you try this?
<script>
	async function loadFoodList() {
        const res = await fetch('https://api.nal.usda.gov/fdc/v1/foods/list?dataType=Foundation&api_key=DEMO_KEY');
        const foodList = await res.json();
        if (!res.ok) {
			throw new Error("Something's wrong");
		}
        return foodList;
    }
	
	const foodListPromise = loadFoodList();
</script>
{#await foodListPromise}
	<p>Loading...</p>
{:then foodList}
	{#each foodList as item}
        <p>{item.description}</p>
    {/each}
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}
You can read more here: https://svelte.dev/tutorial/await-blocks
英文:
Your #await is trying to check the function, not a promise.
Could you try this?
<script>
	async function loadFoodList() {
        const res = await fetch('https://api.nal.usda.gov/fdc/v1/foods/list?dataType=Foundation&api_key=DEMO_KEY');
        const foodList = await res.json();
        if (!res.ok) {
			throw new Error("Something's wrong");
		}
        return foodList;
    }
	
	const foodListPromise = loadFoodList();
</script>
{#await foodListPromise}
	<p>Loading...</p>
{:then foodList}
	{#each foodList as item}
        <p>{item.description}</p>
    {/each}
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}
You can read more here: https://svelte.dev/tutorial/await-blocks
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论