javascript - Firebase 实时数据库 - 多个顺序读取和写入操作,无需嵌套承诺
问题描述
我正在使用 Firebase 实时数据库进行存储。
为了在更新“注释”时更新用户的联系人数据,我需要执行一些顺序操作。我希望为“Note”中包含的每个“affectedUser”更新/推送联系人节点。
下面是我的数据库的粗略表示。
-notes
-note123456 <-- Note being updated
affectedUsers: {'L1234567890ABC': true, 'L0987654321XYZ': true} <-- affectedUsers
-users <-- Compose contact objects from here for all affectedUsers
-L1234567890ABC
name
alias
email
avatar
favouriteColour
-L0987654321XYZ
-contacts <-- Add new contacts here
-L1234567890ABC
-ABCDEFGHIJKLMNO0123 <-- Already added contact
alias
name
-L0987654321XYZ
-ABCDEFGHIJKLMNO0123 <-- Already added contact
我的出发点是需要更新的“affectedUsers”列表 - 用户 ID 列表。
所需的简化工作流程如下所示
- 迭代“affectedUsers”并编写“联系人卡片”
- 然后迭代所有“affectedUsers”并将联系人卡片添加到每个受影响的用户
我当前的代码
const dbRoot = snapshot.ref
affectedUsers = ['-L1234567890ABC', '-L0987654321XYZ']
let promises = [];
affectedUsers.forEach((affectedUser) => {
const ref = dbRoot.child(`users/${affectedUser}`)
promises.push(
ref.once('value', (userSnapshot)=>{
const userNodeData = userSnapshot.val()
const contactObject = {
alias: userNodeData.alias,
name: userNodeData.name
}
return contactObject
);
})
Promise.all(promises).then((contactObjects) => {
let updateContactsPromises = [] //Collect second promise chain
//Check contacts of affectedUsers
affectedUsers.forEach((userId) => {
const ref = dbRoot.child(`contacts/${userId}`)
updateContactsPromises.push(
ref.once('value', (updateUserContactsSnapshots) => {
updateUserContactsNodeData = updateUserContactsSnapshots.val()
//Remove userId from additions, prepare database update object, push data
//...
})
)
})
//Execute second, and last promise chain
Promise.all(updateContactsPromises) //Line 328
.then(()=>{
//...
})
.catch((err)=>{})
})
.then(()=>{
//...
})
.catch((err)=>{})
我意识到嵌套承诺不是一件好事——因为我在执行 firebase 部署时收到警告。;)
328:9 警告避免嵌套承诺承诺/禁止嵌套
328:9 警告避免嵌套承诺承诺/禁止嵌套✖ 2 个问题(0 个错误,2 个警告)
如何确保我的调用在没有嵌套承诺的情况下按顺序执行?
解决方案
问题是当你有一个.then
直接在另一个内部时.then
。通常,这可以通过返回下一个 Promise 来解决,而不是嵌套 then。例如,改变
prom.then(() => {
getAnotherProm().then(handleOther);
});
到
prom.then(() => {
return getAnotherProm()
})
.then(handleOther);
在这里,您可以返回第二个Promise.all
以避免嵌套.then
s:
Promise.all(promises)
.then((contactObjects) => {
let updateContactsPromises = [] //Collect second promise chain
//Check contacts of affectedUsers
affectedUsers.forEach((userId) => {
// ...
})
//Execute second, and last promise chain
return Promise.all(updateContactsPromises)
})
.then((updateContactsValues) => {
// handle resolve value of updateContactsPromises
})
.catch((err) => {
// handle errors
})
请记住仅.catch
在可以正确处理错误的级别上,并且可以将.then
s 链接在一起以避免重复.catch
es。
您还可以使用.map
而不是.forEach
一次构造 Promises 数组,例如:
const dbRoot = snapshot.ref
affectedUsers = ['-L1234567890ABC', '-L0987654321XYZ']
const affectedUserPromises = affectedUsers.map((affectedUser) => {
const ref = dbRoot.child(`users/${affectedUser}`)
return ref.once('value', (userSnapshot) => {
const userNodeData = userSnapshot.val()
return {
alias: userNodeData.alias,
name: userNodeData.name
};
});
});
Promise.all(affectedUserPromises).then((contactObjects) => {
// ...
推荐阅读
- c++ - OpenCV C++如何知道每行的轮廓数进行排序?
- javascript - JS 中是否提升了 const 变量?
- dart - 使用颤振将在线图像uri转换为base64
- spring-boot - p:PickList 在 Spring Boot 中自定义 JSF 转换器
- javascript - react ref在componentDidMount中返回未定义
- bootstrap-4 - 我无法让置顶导航栏与下一个元素引导程序 4 重叠
- jquery - 禁用右键单击 vimeo 播放器
- angular - 如何让这个函数等待一个 HTTP 请求
- python - Python在带有返回调用的函数下添加多重检查
- java - 使用java在谷歌驱动器中获取上传的文件名?