You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte中async函数处理列表时{#each}遍历报错如何解决

错误原因

所有标记为async的函数,无论内部返回什么类型的值,实际对外的返回值永远是Promise对象,不会直接返回你构造的contact_list数组。
你的代码里$: contacts_list = getContacts($contacts)这行响应式语句,最终给contacts_list赋值的是一个Pending状态的Promise,不是可遍历的数组,Svelte的{#each}语法无法遍历Promise类型值,因此抛出遍历错误。
移除async关键字后函数直接同步返回数组,所以可以正常渲染,但这种写法下函数内部无法使用await调用异步接口拉取数据库关联数据。

解决方法

你可以选任意一种适配业务场景的写法,都可以完整保留异步数据拉取逻辑:

  • 方案1:初始赋值空数组,异步逻辑执行完成后再做响应式赋值
    不要直接把async函数的返回值赋给模板遍历的变量,先给遍历变量设初始空数组,在异步逻辑里拿到最终结果后手动更新变量值。修正后的代码如下:
{#each contacts_list as contact}
    <div>{contact}</div>
{/each}

<script>
    import { contacts, user_contacts } from './data-store'
    // 初始给空数组,避免初始渲染时遍历报错
    let contacts_list = []

    // 依赖的store值变化时,自动触发异步拉取逻辑
    $: {
        // 重置为空数组,避免旧数据残留
        contacts_list = []
        getContacts($contacts, $user_contacts)
    }

    async function getContacts(contactsVal, userContactsVal) {
        let contact_list = []
        if (isIterable(userContactsVal)) {
            for (let contact of userContactsVal) {
                // 此处可正常添加await逻辑拉取数据库关联数据,例如:
                // const extraInfo = await fetchContactExtra(contact.id)
                // contact_list.push({...contact, ...extraInfo})
                contact_list.push(contact);
            };
        };
        // 异步操作完成后给响应式变量赋值,自动触发视图更新
        contacts_list = contact_list
    };

    function isIterable (value) {
        return Symbol.iterator in Object(value);
    };
</script>
  • 方案2:使用Svelte内置的{#await}块处理Promise(Svelte 3.29及以上版本支持)
    直接在模板层处理异步逻辑的加载、完成、报错状态,不用手动维护中间变量:
{#await contacts_promise}
    <div>加载中...</div>
{:then contacts_list}
    {#each contacts_list as contact}
        <div>{contact}</div>
    {/each}
{:catch error}
    <div>加载联系人失败:{error.message}</div>
{/await}

<script>
    import { contacts, user_contacts } from './data-store'
    // 依赖变化时重新生成异步Promise
    $: contacts_promise = getContacts($contacts, $user_contacts)

    async function getContacts(contactsVal, userContactsVal) {
        let contact_list = []
        if (isIterable(userContactsVal)) {
            for (let contact of userContactsVal) {
                // 此处可正常编写await异步逻辑
                contact_list.push(contact);
            };
        };
        return contact_list;
    };

    function isIterable (value) {
        return Symbol.iterator in Object(value);
    };
</script>

注意:异步逻辑执行时要做好依赖追踪,不要在async函数里直接读取外层响应式变量/store值,最好把依赖的值作为参数传入函数,避免闭包拿到旧值导致数据不更新。

内容的提问来源于stack exchange,提问作者Psionman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 14:06:28