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;
关键注意点
- signal初始化:不要直接将async函数的返回值(Promise)传入
signal(),应先设置合理的默认值(如空数组、空对象)。 - 异步更新signal:必须等待异步请求完成后,再通过
signal.value = 数据的方式更新状态,这样signal才会存储解析后的实际数据。 - 错误处理:在
fetchData中添加错误捕获,并返回默认值,避免组件因数据未定义而崩溃。 - signal创建方式:
signal是工厂函数,直接调用即可,不要用new signal(),这会导致语法错误。
内容的提问来源于stack exchange,提问作者DarkinStar
相关产品推荐
相关产品推荐

