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

React中用async-await函数仍返回Promise?@preact/signal-react问题

问题分析
  • async函数的特性:所有被async标记的函数,返回值都会被自动包装为Promise——哪怕内部用了await解析异步操作,最终返回的仍然是Promise对象。你直接将fetchData()的返回值传给signal(),自然会把Promise存入signal,而非解析后的实际数据。
  • 初始化时机问题:组件初始化阶段调用fetchData()时,异步请求还处于pending状态,此时signal的初始值就是未完成的Promise。
解决方案

核心思路:先初始化signal为默认值(如空数组、空对象),再通过异步操作获取数据后,更新signal的value属性。推荐使用React的useEffect在组件挂载后触发数据请求。

修正后的完整代码

import { signal } from "@preact/signals-react";
import { useEffect } from "react";
import { FetchAnimeMovieData, FetchPopularData, FetchRecentReleaseData, FetchTopAiringData } from "../functions/AnimeDataFetcher";

function CategoryPage() {
    // 初始化signal为默认空结构,避免存储Promise
    const recentUpdate = signal({ results: [] });
    const topAiring = signal({ results: [] });
    const popular = signal({ results: [] });
    const animeMovies = signal({ results: [] });
    const displayAnime = signal({}); // 修正:signal是函数,直接调用,无需new

    async function fetchData(fetchDataFunction) {
        try {
            return await fetchDataFunction(1);
        } catch(err) {
            console.error("数据请求失败:", err);
            return { results: [] }; // 返回默认值,防止渲染报错
        }
    }

    // 组件挂载后执行异步请求,更新signal
    useEffect(() => {
        const loadAllData = async () => {
            recentUpdate.value = await fetchData(FetchRecentReleaseData);
            topAiring.value = await fetchData(FetchTopAiringData);
            popular.value = await fetchData(FetchPopularData);
            animeMovies.value = await fetchData(FetchAnimeMovieData);
        };
        loadAllData();
    }, []);

    return ( <>
        <div className="container">
            <h1 className="heading">Categories</h1>
            <div className="container">   
                <button>Recent Update</button>
                <button>Top Airing</button>
                <button>Anime Movies</button>
                <button>Popular</button>
            </div>
            {/* 先判断数据是否存在,再渲染 */}
            {recentUpdate.value.results.length > 0 ? (
                recentUpdate.value.results.map((item) => (
                    <p key={item.id}>{item.name}</p>
                ))
            ) : (
                <p>加载中...</p>
            )}            
        </div>
    </> );
}

export default CategoryPage;
关键注意点
  1. signal初始化:不要直接将async函数的返回值(Promise)传入signal(),应先设置合理的默认值(如空数组、空对象)。
  2. 异步更新signal:必须等待异步请求完成后,再通过signal.value = 数据的方式更新状态,这样signal才会存储解析后的实际数据。
  3. 错误处理:在fetchData中添加错误捕获,并返回默认值,避免组件因数据未定义而崩溃。
  4. signal创建方式:signal是工厂函数,直接调用即可,不要用new signal(),这会导致语法错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:23:35