在 forEach 之后使用 Promise.all() 渲染 NodeJS 页面之前等待 Firebase 数据加载
Posted
技术标签:
【中文标题】在 forEach 之后使用 Promise.all() 渲染 NodeJS 页面之前等待 Firebase 数据加载【英文标题】:Wait for Firebase data to load before rendering NodeJS page after forEach with Promise.all() 【发布时间】:2017-05-13 04:53:14 【问题描述】:我正在尝试创建一个从 Firebase 加载多个数据集的页面,然后将它们传递给 NodeJS 呈现的页面。我会很感激一些帮助,以确保在 forEach 迭代之后发生这种情况;也就是说,我不确定如何让 Firebase forEach 迭代成为我的承诺的一部分。
非常感谢!
router.get('/', function(req, res, next)
var getBrands = brandRef.once('value').then(function(snapshot)
var brands = [];
snapshot.forEach(function(childSnapshot)
console.log(childSnapshot.val()['name']);
brands.push('name' : childSnapshot.val()['name'] );
);
return brands;
);
var getStores = storeRef.once('value').then(function(snapshot)
var stores = [];
snapshot.forEach(function(childSnapshot)
stores.push('name' : childSnapshot.val()['name'] );
);
return stores;
);
var getProducts = productRef.once('value').then(function(snapshot)
var products = [];
snapshot.forEach(function(childSnapshot)
products.push('name' : childSnapshot.val()['name'] );
);
return products;
);
console.log(brands, stores, products);
Promise.all([getBrands, getStores, getProducts]).then(function(results)
res.render('index', title: 'MStore Demo Portal', stores: results[0], brands: results[1], products: results[2] );
);
);
【问题讨论】:
看我的回答——你可以把这段代码从后端移动到前端,你所做的就是合并数据库中的结果。 那些是snapshot
s 数组,还是自定义(甚至是异步)forEach
方法?
@Bergi,这是用于快照的内置 Firebase forEach 函数。
如果是异步的,怎么知道什么时候完成?
【参考方案1】:
Firebase 设计为无服务器架构。从长远来看,您不需要标准的 RESTFul Node.js API 服务器。您只需要 Lambda 工作人员。请看:https://github.com/firebase/firebase-queue
将工作放入队列中,工作人员将接手工作并更新 Firebase。当 Firebase 更新时,它会向您的前端发送消息。这一切都是异步的,应该适用于几乎任何应用程序。
拥有 API 服务器也没有什么问题,但实际上并不需要。除非您有充分的理由拥有我认为的 Express API 服务器,否则您可以放弃它。
看起来您对这段代码所做的只是从数据库中获取值,您可以使用前端而不是 API 服务器来执行此操作,并在前端合并结果,这样做会更好事情就是这样。
从字面上看,只需在此处获取 Express 中的代码,并将其移动到您的前端应用程序中:)
【讨论】:
Literally, just take the code that's in Express here, and move it to your front-end app
这实际上是不够的,除了将问题中的代码移动到前端应用程序之外,还有很多工作要做(假设前端应用程序是基于 javascript 的很好假设,它仍然是一个假设)
@JaromandaX 我支持我的 cmets/answer,如果您删除 Express 路由代码行,您基本上可以解除代码并将其放在前端。我是一名后端开发人员,但 Firebase 被设计成一个非常依赖客户端的架构。你直接回答了这个问题,但我想就更大的图景提出一点看法。 Firebase 被称为“无服务器”架构是有原因的。想想这意味着什么。
只是看着firebase-queue
,似乎涉及很多设置(虽然我可能是错的) - 我没有质疑你的答案,我正在尝试从中学习:p
@JaromandaX 我是个老派,我不喜欢闪亮的东西。然而 Firebase 队列很有意义,而 Lambda 架构才是真正的交易。一般来说,我喜欢遵循 KISS,在这种情况下,标准的 RESTful API 会看起来是 KISS 方式。但是,一旦您对 Lambda 和 Firebase 队列进行了一些工作,您就会看到好处。 Firebase-Queue 是使用 Firebase DB 进行后端开发的规范方式。 RESTful API 服务器不是规范的方式。
此外,TMK、Firebase 也可以启动您的应用。您确实不需要需要 API 服务器来提供 index.html。如果这个问题在你的脑海中。当我第一次开始使用 Firebase 时,我认为至少您需要自己的服务器来发送索引页面,然后其他所有内容都将是对 Firebase 的“JSON 调用”。但我认为 Firebase 也可以提供您的 html 文件。【参考方案2】:
您的代码看起来 99% 正常
router.get('/', function(req, res, next)
var getBrands = ...;
var getStores = ...;
var getProducts = ...;
到目前为止一切顺利(甚至没有复制代码,因为它是正确的
console.log(brands, stores, products);
品牌、商店和产品在 .then
回调中声明,因此无论如何,此时它们始终是未定义的
Promise.all([getBrands, getStores, getProducts]).then(function(results)
res.render('index', title: 'MStore Demo Portal', stores: results[0], brands: results[1], products: results[2] );
);
);
上面唯一的“问题”是,由于您在 Promsie.all 中订购了getBrands, getStores, getProducts
,结果将是brands, stores, products
但是,您似乎认为(基于索引)结果将是 stores, brands, products
- 在代码中交换索引 0 和 1,或者调用
Promise.all([getStores, getBrands, getProducts]).then
提示,如果您使用的是足够新的 node.js,您可以执行以下操作
Promise.all([getStores, getBrands, getProducts]).then(([stores, brands, products]) =>
res.render('index', title: 'MStore Demo Portal', stores, brands, products )
);
【讨论】:
这是一个编码方案,但我认为这段代码不需要在API服务器上,只需将这段代码移到前端! 这是问题的“解决方案”-答案的唯一真实部分是console.log
不会显示任何有用的信息,尽管 0 1 换位,代码确实是正确的 - 完全不知道引入 firebase-queue
是如何回答 OP 的问题的
非常感谢您的帮助和最后的速记,Jaromanda!我不敢相信我没有发现这个问题。以上是关于在 forEach 之后使用 Promise.all() 渲染 NodeJS 页面之前等待 Firebase 数据加载的主要内容,如果未能解决你的问题,请参考以下文章
在 forEach 之后使用 Promise.all() 渲染 NodeJS 页面之前等待 Firebase 数据加载
如何在 ForEach 循环之后保留对象变量更改。 Javascript
在 int 值之后对 ForEach 中的 FireStore 数据进行排序