Firebase:snapshot.val 不是函数或其返回值不可迭代
Posted
技术标签:
【中文标题】Firebase:snapshot.val 不是函数或其返回值不可迭代【英文标题】:Firebase: snapshot.val is not a function or its return value is not iterable 【发布时间】:2019-08-10 22:53:52 【问题描述】:所以我正在使用 Express、Firebase 和 ReactJS 创建一个小型应用程序。 我偶然发现了 Firebase snapshot.val 的问题
express 上的这部分代码是通过 ID 为我的旅行提供服务并获取所有信息。对于所有旅行都很好,但是当我尝试去单次旅行时,它会返回这个错误
如果我将它解构为一个数组:
UnhandledPromiseRejectionWarning: TypeError: snapshot.val is not a function or its return value is not 可迭代
如果我将它解构为一个对象:
TypeError: 无法解构“未定义”的属性
trip
或 '空'。
我完全感到困惑,找不到解决方案。
这里是 express 部分代码:
const firebase = require('firebase');
const reference = () => firebase.database().ref('/trips')
exports.getSingle = async (id) =>
//const snapshot = await reference()
// .orderByChild('id')
// .equalTo(id)
// .limitToFirst(1)
// .once('value');
// const [trip] = snapshot.val();
// return trip
const snapshot = await reference()
.orderByChild('id')
.equalTo(parseInt(id, 10))
.limitToFirst(1)
.once('value');
let trip = [];
snapshot.forEach(function (tripSnapshot)
tripStorage = tripSnapshot.val();
console.log(tripStorage);
trip.push(tripStorage);
);
console.log(trip);
return trip;
;
exports.getAll = async () =>
const snapshot = await reference().once('value');
return snapshot.val();
;
我在前端获取旅行:
componentDidMount()
fetch("/api/trips/get/" + this.state.id)
.then(res => res.json())
.then(trip =>
this.setState(
trip
, () => console.log("Trips fetched...", trip))
);
旅行控制器:
const express = require('express');
const route = express.Router();
const tripUtil = require('../utils/tripUtil');
route.get('/getAll', async (req, res) =>
const trips = await tripUtil.getAll();
res.json(trips);
);
route.get('/get/:id', async (req, res) =>
const id = req.params;
const trip = await tripUtil.getSingle(id);
if (trip)
res.json(trip);
else
res.status = 400;
res.json(
error: 'trip not found'
);
);
module.exports = route;
并像这样从对象映射属性:
this.state.trip.itinerary.days.map((day, i) =>
return (
<div key=i className="trip-single-item__day">
<div className="trip-single-item__day-header">
<div className="trip-single-item__day-title">
day.title
</div>
<div className="trip-single-item__day-subtitle">
day.subtitle
</div>
<div className="trip-single-item__day-date">
day.date
</div>
</div>
<div className="trip-single-item__day-body">
<div className="trip-single-item__day-descritpion">
day.description
</div>
</div>
</div>
);
)
这里是单程图片Single trip in firebase
有什么建议或方向吗?谢谢
【问题讨论】:
为什么将trip
常量放在方括号中? const [trip] = snapshot.val();
您是否尝试从snapshot.val()
访问属性trip
,例如const trip = snapshot.val();
如果我按照你的建议放置它,那么我会得到 UnhandledPromiseRejectionWarning: TypeError: Cannot destructure property trip
of 'undefined' or 'null'。但我认为这是解构 firebase 对象的正确方法?
这只是一个问题,而不是一个建议 :) 你能编辑你的帖子并写下错误吗:it returns me this error and I am totally baffled
完成,感谢您的提示。我为什么要这样做?当我想一想它是否作为对象存储在 firebase 中时,没有逻辑可以通过方括号访问它,但现在我更加困惑为什么行程未定义。
id
属性是单个 trip
对象的嵌套属性吗?如果没有,你可以这样访问它:reference().child(id)
.once('value')`
【参考方案1】:
Firebase 通常建议不要将数据作为数组存储在实时数据库中(尽管存在一些例外情况):https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html
我猜是因为某种原因,您的快照值没有被呈现为数组,而是一个带有数字键的对象。造成这种情况的一个原因可能是 Firebase 中的键不是严格按顺序排列的,因为 Firebase 只会在数据的键以 0 开头且没有间隙的情况下将您的数据呈现为数组。
你能试试这个代码看看它是否有效吗?
exports.getSingle = async (id) =>
const snapshot = await reference()
.orderByChild('id')
.equalTo(id)
.limitToFirst(1)
.once('value');
const queryResult = snapshot.val()
console.log(queryResult) // Make note of the object shape here. Make sure there are actually results.
const trip = Object.values(queryResult)[0]
return trip;
;
【讨论】:
它只是将 queryResult 返回为 null,因此对数据库的引用似乎不好。我还编辑了按 ID 服务的控制器代码,也许我在那里遗漏了什么? 似乎 .orderByChild、.equalTo 和 limitToFirst 有问题,我不明白为什么。 您从 Express 获得并传递给getSingle
的 :id
参数很可能是一个字符串,而 Firebase 中行程的 id
属性是一个数字。这可能会导致您的 equalTo
查询失败,因为它找不到 id === "1" 的项目。试试equalTo(parseInt(id, 10))
看看能不能解决。
是的,这解决了带有 id 的部分,这显然是一个字符串。但是,在我不得不更新将snapshot.val()
推送到trip 数组的代码之后,发生了相当奇怪的事情,并且推送的元素在推送之前在JSON 中呈现良好,但是当推送里面的嵌套项目时显示为[object Object]。
当使用 console.log 登录到控制台时,深度嵌套的 JSON 对象通常会显示为 [Object] 或 [object Object]。这个是正常的。您可以尝试console.log(JSON.stringify(trips, null, 2))
序列化对象并将其漂亮地打印为字符串。【参考方案2】:
可能是 UnhandledPromiseRejectionWarning。
用 then/catch 处理你的快照
exports.getSingle = async (id) =>
await reference()
.orderByChild('id')
.equalTo(id)
.limitToFirst(1)
.once('value').then(snapshot =>
const [trip] = snapshot.val();
return trip
// console.log(post.id) if required
)
;
【讨论】:
是的,它给出了 UnhandledPromiseRejectionWarning 我已经编辑了错误。正在查看 firebase 文档并尝试了一些您发布的变体,但仍然给我同样的错误。以上是关于Firebase:snapshot.val 不是函数或其返回值不可迭代的主要内容,如果未能解决你的问题,请参考以下文章
错误“snapshot.val”不是 Google Cloud Functions 中的函数
注册时无法将个人资料信息添加到 Firebase 集合中(vue | firebase)
solr 可以返回函数值(不是 solr 分数或文档字段)吗?