React Native配合Firebase使用async/await时执行顺序异常问题
问题原因
- Firebase Realtime Database 的
on()方法是用于注册实时数据监听器的API,返回值为监听器取消函数,不是Promise,因此外层的await不会等待监听器回调执行完成,注册完监听器后就会直接执行后续的console.log('here1')和分支判断逻辑,此时checkExist还未被更新,所以第一次输出here1 false。 - 代码中
await firebase.database().ref("Tasks").child(snapshot2.key).child(task.taskname)的写法无效,ref()方法返回的是数据库引用对象,并非异步Promise,await对其没有作用。后续的countChild.on("value")同样是监听器注册逻辑,回调会异步执行,不会阻塞外层代码。 - 输出中出现多次
here1是因为on()注册的监听器会持续接收数据更新事件,每次数据变化都会触发回调,导致重复执行状态更新。
解决方案
如果你的需求是仅单次查询数据完成校验,将所有on()方法替换为返回Promise的once()方法,调整异步逻辑顺序,把后续的分支判断放到所有异步查询完成之后执行:
toggleisModal = async () => { const task = this.props.task; let checkExist = false; // 单次获取Tasks下的所有子节点,用once('value')代替on('child_added') const tasksSnapshot = await firebase.database().ref("Tasks").once("value"); // 遍历所有子节点 for (const snapshot2 of tasksSnapshot.forEach(childSnap => { if (childSnap.exists()) { // 单次查询对应taskname的子节点数量 const snapshot3 = await firebase.database() .ref("Tasks") .child(childSnap.key) .child(task.taskname) .once("value"); if (snapshot3.numChildren() >= 6) { checkExist = true; console.log("here2 ", checkExist); return true; // forEach返回true会终止遍历 } } })); // 所有查询完成后再执行后续逻辑 console.log("here1 ", checkExist); if (checkExist === true) { this.setState({ showTaskVisible: false, checkExist: true }); } else { this.setState({ showTaskVisible: !this.state.showTaskVisible, checkExist: false }); } };
如果确实需要使用实时监听的能力,不要把后续分支判断写在监听器注册逻辑的后面,而是把状态更新和分支逻辑全部放到监听器的回调内部执行。
内容的提问来源于stack exchange,提问作者user123456
相关产品推荐
相关产品推荐

