Нет, в javascript нет возможности метапрограммирования, аналогично рубину method_missing. Интерпретатор просто вызывает ошибку, которую вызывающий код может уловить, но не может быть обнаружен объектом, к которому обращаются. Здесь есть некоторые ответы на определение функций во время выполнения, но это не одно и то же. Вы можете много метапрограммировать, изменять конкретные экземпляры объектов, определять функции, выполнять такие функциональные функции, как воспоминания и декораторы. Но нет динамического метапрограммирования отсутствующих функций, как в ruby или python.
Когда все электронные письма участников еще не существуют в документах, функции работают должным образом, и console.log () выводит идентификаторы итогового документа: hAvJ3qPq821tq1q2rrEv, 0tjeKB1aW8jsOAse5fcP
blockquote>Это потому что он разрешает следующий оператор возврата:
return document_id;
Однако, когда хотя бы один адрес электронной почты связан с существующим документом, обещания addParticipant () не разрешаются ни к чему
blockquote>Потому что не ничего не возвращает. Последнее ваше утверждение:
// 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; });
Это , а не возврат любого идентификатора. Это просто
forEach
. Пример исправления будет выглядеть так:// Return the id return querySnapshot[0].document_id;
Разобрался с некоторыми подсказками @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);
}
};
С Promise.all
, если даже одно обещание не выполняется, вы не получите ни того, ни другого. Возьмите следующий пример:
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
, как вам удобно.