我正在使用Firebase Realtime数据库进行存储。
为了在更新“注释”时为用户更新联系人数据,我需要执行一些顺序操作。我希望为“注释”中包含的每个“ 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列表。
所需的,简化的工作流程如下所示
我当前的代码
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)=>{})
我意识到嵌套的Promise不是一件好事-因为执行Firebase部署时会收到警告。 ;)
328:9警告避免嵌套promises promise / no-nesting
328:9 警告避免嵌套promises promise / no-nesting✖2个问题(0个错误,2个警告)
如何确保我的调用按顺序执行而没有嵌套承诺?
答案 0 :(得分:1)
问题是当您直接在另一个.then
内有一个.then
时。通常,可以通过返回下一个Promise来解决此问题,而不是先嵌套。例如,更改
prom.then(() => {
getAnotherProm().then(handleOther);
});
到
prom.then(() => {
return getAnotherProm()
})
.then(handleOther);
在这里,您可以返回第二个Promise.all
以避免嵌套.then
:
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
链接在一起以避免避免重复.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) => {
// ...