JavaScript中如何正确调用async函数?解决setLoading执行时机问题
正确处理Promise并控制loading状态的方案
你判断的没错,setLoading(false)确实会在Promise解析完成前就执行——因为Promise的回调属于异步任务,会被放到事件队列中等待执行,而同步代码setLoading(false)会优先完成,导致loading状态提前结束。
下面是两种可行的解决方案:
方案一:使用Promise的finally方法
直接在Promise调用链末尾添加finally,它会在Promise无论成功(resolve)还是失败(reject)后都执行,刚好适合用来重置loading状态:
const onPress = () => { setLoading(true); getEvents() .then((eventList) => setEvents(eventList)) .catch((error) => alert(error)) .finally(() => setLoading(false)); // 无论请求成功/失败都会执行 };
方案二:使用async/await语法
这种写法逻辑更线性,可读性更高:
const onPress = async () => { setLoading(true); try { // 等待getEvents的Promise完成 const eventList = await getEvents(); setEvents(eventList); } catch (error) { // 捕获请求失败的错误 alert(error); } finally { // 无论成功失败都重置loading setLoading(false); } };
额外优化:简化getEvents函数
你的getEvents手动包裹了一层Promise,其实完全没必要——因为firebase.firestore().collection('GoodEvents').get()本身就返回Promise,可以直接简化:
const getEvents = () => { return firebase.firestore().collection('GoodEvents').get() .then((snapshot) => { // 用map替代forEach+push,写法更简洁 return snapshot.docs.map(doc => Event.fromFirestore(doc)); }); };
如果get()请求失败,Promise会自动进入reject状态,上层的catch会捕获到错误,不需要手动在getEvents里处理reject。
内容的提问来源于stack exchange,提问作者user22766469
相关产品推荐
相关产品推荐

