我有一个函数,该函数映射一个数组的每个元素(在这种情况下为电子邮件地址),产生一个应答数组,应解析为Firebase自动生成的文档ID(即hAvJ3qPq821tq1q2rrEv, 0tjeKB1aW8jsOAse5fcP
)。
async function addMultipleParticipants(participant_emails: Array<string>) {
console.log("Parallelizing participant processing");
const promises = participant_emails.map(addParticipant);
const document_ids = await Promise.all(promises);
console.log("Final document ids: " + document_ids);
return document_ids;
};
这里是返回文档ID的函数,具体取决于它是否可以找到与电子邮件地址关联的现有文档,或者是否需要创建新文档。
async function addParticipant(email_address: string) {
try {
console.log("Querying for person");
const query = await db.collection('people')
.where('emails', 'array-contains', email_address)
.limit(1);
const querySnapshot = await query.get();
if (!querySnapshot.empty) {
console.log("Document exists for email " + email_address);
// TODO: There is only one, so we shouldn't have to iterate
querySnapshot.forEach(function(docRef: any) {
console.log("New document id: " + docRef.id);
const document_id = docRef.id;
return document_id;
});
} else {
console.log("Creating person with " + email_address);
const fields = {emails: [email_address]};
try {
const docRef = await db.collection('people').add(fields);
console.log("New document id: " + docRef.id);
const document_id = docRef.id;
return document_id;
} catch (err) {
console.log("Error adding document:", err);
}
}
} catch (err) {
console.log("Error getting document:", err);
}
};
当文档中还没有所有参与者的电子邮件时,该功能将按预期工作,并且console.log()
输出Final document ids: hAvJ3qPq821tq1q2rrEv, 0tjeKB1aW8jsOAse5fcP
。
但是,当至少一个电子邮件地址与一个现有文档相关联时,来自addParticipant()
的承诺将无法解决任何问题,并且console.log()
会输出Final document ids: ,
。
在这种情况下,我需要做些什么来确保在addMultipleParticipants()
中正确解析承诺数组?
答案 0 :(得分:1)
当文档中还没有所有参与者的电子邮件时,该功能将按预期运行,console.log()输出最终文档ID:hAvJ3qPq821tq1q2rrEv,0tjeKB1aW8jsOAse5fcP
这是因为它解析为以下return语句:
return document_id;
但是,当至少一个电子邮件地址与一个现有文档相关联时,addParticipant()的承诺不会解析为任何内容
因为它不返回任何内容。您的最后一条语句是:
// TODO: There is only one, so we shouldn't have to iterate
querySnapshot.forEach(function(docRef: any) {
console.log("New document id: " + docRef.id);
const document_id = docRef.id;
return document_id;
});
不是返回任何ID。它只是一个forEach
。修复示例如下:
// Return the id
return querySnapshot[0].document_id;
答案 1 :(得分:1)
如果使用Promise.all
,即使1个承诺都失败了,您也不会得到任何结果。请看以下示例:
const get = async () => {
return Promise.all([
new Promise((res, rej) => {
setTimeout(() => {
res('data!')
}, 1000)
}),
new Promise((res, rej) => {
setTimeout(() => {
rej('error!')
}, 2000)
})
]);
}
const start = async () => {
const response = await get()
console.log(response)
}
start()
您只会遇到Uncaught (in promise) error!
错误。
现在,如果您想解决这个问题以至少得到一些回报,则可以对每个承诺使用catch
,如下所示:
const get = async () => {
return Promise.all([
new Promise((res, rej) => {
setTimeout(() => {
res('data!')
}, 1000)
}).catch(err => {
return null
}),
new Promise((res, rej) => {
setTimeout(() => {
rej('error!')
}, 2000)
}).catch(err => {
return null
})
]);
}
const start = async () => {
const response = await get()
console.log(response)
}
start()
这将给您["data!", null]
,您可以按照自己的意愿处理null
。
答案 2 :(得分:1)
用@basarat的一些提示弄清楚了它。第一个结果应该有明确的回报,而不是for循环:return querySnapshot.docs[0].id;
。完整的修改功能如下:
async function addParticipant(email_address: string) {
try {
console.log("Querying for person");
const query = await db.collection('people')
.where('emails', 'array-contains', email_address)
.limit(1);
const querySnapshot = await query.get();
if (!querySnapshot.empty) {
console.log("Document exists for email " + email_address);
return querySnapshot.docs[0].id;
} else {
console.log("Creating person with " + email_address);
const fields = {emails: [email_address]};
try {
const docRef = await db.collection('people').add(fields);
console.log("New document id: " + docRef.id);
const document_id = docRef.id;
return document_id;
} catch (err) {
console.log("Error adding document:", err);
}
}
} catch (err) {
console.log("Error getting document:", err);
}
};