Я настраиваю экспресс-приложение для обработки SSR для моего приложения реагирования. Мне нужно получить доступ к содержимому Firebase по одному из моих маршрутов, который определен как логическое значение в моем файле rout.js.
export default [
{
component: Home,
path: '/',
exact: true,
fetchInitialData: true
},
{
component: About,
path: '/about',
fetchInitialData: false
}
];
Это импортируется через мое экспресс-приложение как обычное серверное приложение, чтобы определить, имеет ли для этого логического значения для маршрута значение 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
Я столкнулся с препятствием на пути к API Firebase, потому что я не могу включить SDK Firebase-Admin в свое приложение реакции. Поэтому я должен запустить его в экспресс-среде и передать данные в качестве подпорки, поэтому я использую логическое значение для требуемых данных вместо передачи функции непосредственно в приложение.
Я не могу использовать обычный firebase-sdk, потому что мне нужно использовать функцию хранилища getDownloadURL, которая использует XMLHttpRequest, который не совместим с сервером, только с браузером!
Я определил свою собственную функцию getDownloadURL в файле экспресс-приложения, которая принимает параметр запроса в качестве идентификатора документа и обрабатывает 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 и в конечном итоге получит photoURL из API хранилища, который я возвращаю вызывающему объекту в качестве объекта.
Я пытался использовать 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 {};
}
}
Тем не менее, результат этой функции всегда неопределен, и я не уверен, как это исправить в этой точке. Любая помощь приветствуется. Спасибо.