【发布时间】:2019-10-05 12:15:12
【问题描述】:
我正在设置一个快速应用程序来处理我的反应应用程序的 SSR。我需要访问我的一条路由上的 Firebase 内容,该路由在我的 routes.js 文件中定义为布尔值。
export default [
{
component: Home,
path: '/',
exact: true,
fetchInitialData: true
},
{
component: About,
path: '/about',
fetchInitialData: false
}
];
这是通过我的 express 应用程序作为普通服务器端应用程序导入的,以确定路由是否将该布尔值设置为 true,然后我可以将函数的结果作为道具传递给我的应用程序的组件。
app.get('*', async (req, res) => {
//Get the matching route object for the URL
const activeRoute = routes.find((route) => matchPath(url.parse(req.url).pathname, route)) || {}
let interaction = {}
const context = {};
const modules = [];
//If the route object has a fetchInitialData boolean as truthy, set interaction to the result of getDownloadURL
if(activeRoute.fetchInitialData){
interaction = await getDownloadURL(req.query.id)
}
//THIS IS UNDEFINED, despite using async/await.
console.log(interaction)
//Interaction should be set from here. Process rest of app logic
我在使用 firebase 的 API 时遇到了障碍,因为我无法在我的 react 应用程序中包含 firebase-admin SDK。因此,我必须在 express 环境中运行它并将数据作为道具传递,因此我使用布尔值作为所需数据而不是将函数直接传递到应用程序的原因。 我不能使用普通的 firebase-sdk,因为我需要使用存储 getDownloadURL 函数,该函数使用与服务器不兼容的 XMLHttpRequest,仅与浏览器兼容!
我在 express 应用程序文件中定义了自己的 getDownloadURL 函数,该函数将查询参数作为文档 ID,并将处理存储在该文档中的图像的 downloadURL。
const getDownloadURL = (path) => {
if(path){
firestore.collection('interactions').doc(path).get()
.then(doc => {
bucket
.file(doc.data().photoPath)
.getSignedUrl({
action: 'read',
expires: '03-09-2999'
})
.then(photoURL => {
const interaction = {
date: doc.data().date,
venue: doc.data().venue,
photoURL: photoURL
}
//console.log(interaction) <<<<< this returns the valid data.
return interaction;
}).catch(e => console.log(e));
}).catch(e => console.log(e));
}else{
return {};
}
}
这将处理 firebase 文档并最终得到来自存储 API 的 photoURL,我将其作为对象返回给调用者。
我尝试按照本指南中的结构使用 Promises 而不是 async/await:https://tylermcginnis.com/react-router-server-rendering
const activeRoute = routes.find((route) => matchPath(url.parse(req.url).pathname, route)) || {}
const promise = activeRoute.fetchInitialData
? getDownloadURL(req.query.id)
: Promise.resolve()
promise.then((data) => {
//Rest of app logic, data is still undefined
我没有从函数中返回对象,而是返回了 firebase 存储承诺并处理了来自调用者的承诺。
const getDownloadURL = (path) => {
if(path){
firestore.collection('interactions').doc(path).get()
.then(doc => {
return bucket
.file(doc.data().photoPath)
.getSignedUrl({
action: 'read',
expires: '03-09-2999'
})
}).catch(e => console.log(e));
}else{
return {};
}
}
但是,此函数的结果始终未定义,我现在不确定如何修复它。任何帮助将非常感激。谢谢。
【问题讨论】:
-
你永远不会返回
firebase.collection....在getDownloadUrl中创建的承诺。 -
如果我仍然需要访问该承诺中的数据,我将如何返回它,例如照片网址?我可以在调用者中处理这些数据吗?
-
只需在
firestore.collection...之前添加return。确保它在同一行。您可能还想修改您的 else 语句以返回Promise.resolve({})看起来您的其余代码将按原样工作。如果不是,您可能需要仔细检查activeRoute.fetchInitialData是否是您所期望的。 -
如果你的 Promise 解析为另一个 Promise,那么你也需要在该 Promise 上调用
then。尝试使用调试器,或者只是 console.log 你在每个 then 块中获得的数据以查看它是什么类型的数据。 -
您好,感谢您的帮助。我发表了一篇关于我的更改的帖子,我让它与你所说的一致,但也许我的解决方案有点笨拙?您可能会采取什么方式来优化它?
标签: reactjs firebase express async-await google-cloud-firestore