使用async/await时出现ReferenceError: updateSingle未定义问题求助
问题解决指南
1. 直接修复 ReferenceError: updateSingle is not defined
类内部调用自身方法必须使用this关键字,你在updateAll里直接写updateSingle,JS会认为这是全局函数,导致找不到定义。修改如下:
async updateAll(datesArr, apiManager) { // 先修正this的问题,后续再优化异步逻辑 for (const date of datesArr) { await this.updateSingle(date, apiManager); } }
2. 修复updateSingle中的异步遍历问题
forEach不支持异步等待,你在forEach里写的async id => {...}会生成一堆未被等待的Promise,导致updateSingle在所有API请求和数据库写入完成前就提前返回。推荐两种修复方案:
方案1:顺序执行(适合避免API请求并发过高)
async updateSingle(day, apiManager) { for (const id of idList) { const reference = ref(this.db, `${day}/${id}`); const data = await apiManager.getDataApi(day, id, apiManager.season); await set(reference, data); // set是异步方法,必须加await } }
方案2:并发执行(效率更高,注意API限流)
async updateSingle(day, apiManager) { await Promise.all(idList.map(async id => { const reference = ref(this.db, `${day}/${id}`); const data = await apiManager.getDataApi(day, id, apiManager.season); return set(reference, data); })); }
3. 优化updateAll的异步逻辑
同样,原forEach无法等待每个updateSingle完成,改成以下两种方式:
顺序执行
async updateAll(datesArr, apiManager) { for (const date of datesArr) { await this.updateSingle(date, apiManager); } }
并发执行(最多10个节点,并发压力可控)
async updateAll(datesArr, apiManager) { await Promise.all(datesArr.map(date => this.updateSingle(date, apiManager))); }
4. 修复removeOldData的异步问题
当前removeOldData是同步方法,但onValue是异步回调,方法返回时foundOldDates还未被正确赋值,导致主程序里的dateRemoved永远为false。改成异步方法,用Promise包裹:
async removeOldData(datesArr) { const rootRef = ref(this.db, "/"); return new Promise((resolve) => { let foundOldDates = false; onValue(rootRef, (snapshot) => { const deleteTasks = []; snapshot.forEach(dateSnap => { if (!datesArr.includes(dateSnap.key)) { const oldDateRef = ref(this.db, `${dateSnap.key}/`); deleteTasks.push(remove(oldDateRef)); foundOldDates = true; } }); // 等待所有删除操作完成后返回结果 Promise.all(deleteTasks).then(() => resolve(foundOldDates)); }, { onlyOnce: true }); }); }
主程序调用时需添加await:
dateRemoved = await firebaseManager.removeOldData(dateManager.dates);
完整修改后的代码
FirebaseManager类
import { initializeApp } from "firebase/app"; import { getDatabase, ref, remove, set, onValue } from "firebase/database"; import { ApiManager } from './api_manager.js'; import { idList } from '../data/data.js'; import { DateManager } from "./date_manager.js"; export class FirebaseManager { constructor() { this.firebaseConfig = { ... }; this.app = initializeApp(this.firebaseConfig); this.db = getDatabase(); } async updateSingle(day, apiManager) { await Promise.all(idList.map(async id => { const reference = ref(this.db, `${day}/${id}`); const data = await apiManager.getDataApi(day, id, apiManager.season); return set(reference, data); })); } async updateAll(datesArr, apiManager) { await Promise.all(datesArr.map(date => this.updateSingle(date, apiManager))); } async removeOldData(datesArr) { const rootRef = ref(this.db, "/"); return new Promise((resolve) => { let foundOldDates = false; onValue(rootRef, (snapshot) => { const deleteTasks = []; snapshot.forEach(dateSnap => { if (!datesArr.includes(dateSnap.key)) { const oldDateRef = ref(this.db, `${dateSnap.key}/`); deleteTasks.push(remove(oldDateRef)); foundOldDates = true; } }); Promise.all(deleteTasks).then(() => resolve(foundOldDates)); }, { onlyOnce: true }); }); } }
主程序
import { FirebaseManager } from "./firebase_manager.js"; import { ApiManager } from './api_manager.js'; import { DateManager } from './date_manager.js'; async function main() { let apiManager = new ApiManager(); let dateManager = new DateManager(); let firebaseManager = new FirebaseManager(); await apiManager.getCurrentSeason(); await firebaseManager.updateAll(dateManager.dates, apiManager); let countDaily = 0; let dateRemoved = false; while(true) { dateManager.update(); if(countDaily >= 360) { await apiManager.getCurrentSeason(); countDaily = 0; } await firebaseManager.updateSingle(dateManager.getToday(), apiManager); dateRemoved = await firebaseManager.removeOldData(dateManager.dates); if(dateRemoved) { await firebaseManager.updateAll(dateManager.dates, apiManager); dateRemoved = false; } countDaily++; await new Promise(r => setTimeout(r, 240000)); } } main();
内容的提问来源于stack exchange,提问作者bragi
相关产品推荐
相关产品推荐

