Firebase实时数据库:能否用set()写入API返回的JSON数据?
问题:Firebase实时数据库写入无效果,无法存储足球API数据
我正在开发一款展示足球实时数据的应用,后端从API获取JSON格式的足球数据,希望将其存入Firebase实时数据库以实现应用内的实时数据展示。数据库顶层需为固定时间区间的日期,每个日期下嵌套API返回的JSON数据。目前尝试使用set()方法写入数据,但没有任何效果,以下是我的代码实现及API请求方法:
import { initializeApp } from "firebase/app"; import { getDatabase, ref, set } from "firebase/database"; import { getDates } from './dates.js'; import { getDataApi, getCurrentSeason } from './api_manager.js'; import { idList } from '../data/data.js'; const firebaseConfig = { ... }; const app = initializeApp(firebaseConfig); const db = getDatabase(); function update() { var startDate = new Date(); var season = getCurrentSeason().then(val => val); var datesArr = getDates(startDate, 7); datesArr.forEach(date => { idList.forEach(id => { const reference = ref(db, `${date}/${id}`); var data = getDataApi(date, id, season); set(reference, data); }); }); } update();
以下是从API获取数据的方法:
import fetch from 'node-fetch'; const options = { method: 'GET', headers: { ... } }; export async function getDataApi(date, leagueId, season) { const url = `https://api-football-v1.p.rapidapi.com/v3/fixtures?date=${date}&league=${leagueId}&season=${season}`; try { let response = await fetch(url, options); let json = await response.json(); return json['response']; } catch (error) { console.log("Error: " + error); } } export async function getCurrentSeason() { const url = 'https://api-football-v1.p.rapidapi.com/v3/leagues?id=39¤t=true'; try { let response = await fetch(url, options); let json = await response.json(); return json['response'][0]['seasons'][0]['year']; } catch (error) { console.log("Error: " + error); } }
问题分析与解决方案
核心问题
代码存在异步处理错误,导致set()方法未拿到有效数据就执行写入,同时循环未等待异步操作完成,引发一系列问题:
getCurrentSeason()是异步函数,直接赋值得到的是Promise对象,而非实际赛季年份,导致API请求参数错误;getDataApi()返回Promise,直接传给set()会写入无效的Promise对象,而非API返回的JSON数据;forEach不支持异步等待,所有请求和写入同时触发,可能触发限流或未正确处理结果。
修复后的代码
将update改为异步函数,用await处理所有异步操作,改用for...of循环支持异步等待:
import { initializeApp } from "firebase/app"; import { getDatabase, ref, set } from "firebase/database"; import { getDates } from './dates.js'; import { getDataApi, getCurrentSeason } from './api_manager.js'; import { idList } from '../data/data.js'; const firebaseConfig = { ... }; const app = initializeApp(firebaseConfig); const db = getDatabase(); async function update() { const startDate = new Date(); // 等待获取真实的赛季年份 const season = await getCurrentSeason(); const datesArr = getDates(startDate, 7); // 使用for...of确保每一步异步操作完成后再执行下一步 for (const date of datesArr) { for (const id of idList) { const reference = ref(db, `${date}/${id}`); // 等待API返回数据 const data = await getDataApi(date, id, season); // 有数据才写入,避免空值 if (data) { await set(reference, data); console.log(`成功写入:${date}/${id}`); } else { console.log(`无数据:${date}/${id}`); } } } } // 捕获整个流程的错误,便于排查 update().catch(error => { console.error("更新失败:", error); });
额外优化建议
- 权限检查:确认Firebase实时数据库的安全规则允许写入,测试阶段可临时设置开放规则(上线前必须修改为严格规则):
{ "rules": { ".read": true, ".write": true } } - 限流处理:若API或Firebase有请求频率限制,可在循环中添加延迟,避免触发限流:
await new Promise(resolve => setTimeout(resolve, 1000)); // 每次请求间隔1秒 - 参数验证:确保
date格式为YYYY-MM-DD(符合API要求),idList中的联赛ID正确,避免API返回空数据。
内容的提问来源于stack exchange,提问作者bragi
相关产品推荐
相关产品推荐

