Ваша проблема вызвана следующими строками:
const promises = [];
jobs.forEach(job => {
promises.push(job.val());
});
return Promise.all(promises);
job.val()
возвращает объект (данных), а не обещание, поэтому Promise.all()
неправильно интерпретирует его как разрешенное обещание без значения. В следующем блоке кода массив jobs
представляет собой массив undefined
значений, а не данных, которые вы ожидали.
Чтобы исправить это, вместо этого вы должны вернуть массив значений вместо использования Promise.all()
.
const jobValues = [];
jobs.forEach(job => {
jobValues.push(job.val());
});
return jobValues;
Но поскольку здесь нет асинхронной работы, вы можете сгладить свою цепочку Обещаний. Таким образом, вы будете использовать меньше памяти, потому что вам не понадобится массив, содержащий все ваши job.val()
объекты одновременно.
exports.foo = functions.database
.ref("/candidates/{jobTrack}/{candidateId}")
.onCreate((snap, context) => {
const candidate = snap.val().candidate;
const jobTrack = context.params.jobTrack;
const jobsRef = admin.database().ref("jobs");
return jobsRef
.child(jobTrack)
.once("value")
.then(jobs => {
const promises = []; // will contain any team feed update promises
jobs.forEach(jobSnapshot => { // This is DataSnapshot#forEach
const job = jobSnapshot.val();
const percent = getMatchedPercent(candidate, job);
if (percent >= 0.9) {
promises.push(
admin
.database()
.ref("feeds")
.child(job.feedId)
.child("upcomingWeek")
.push(candidate) // add to team's feed
);
}
});
return Promise.all(promises);
})
.catch(err => {
console.log("Failed to update team feeds: ", err);
});
});
Однако, это все еще имеет другую проблему, когда некоторые каналы Обновления могут быть успешными, а другие могут завершаться с ошибкой, в результате чего база данных остается в неизвестном состоянии Поэтому вместо этого вы можете рассмотреть возможность записи в базу данных атомарно (все данные записываются или вообще ничего не пишется).
Этого можно достичь, используя:
exports.foo = functions.database
.ref("/candidates/{jobTrack}/{candidateId}")
.onCreate((snap, context) => {
const candidate = snap.val().candidate;
const jobTrack = context.params.jobTrack;
const jobsRef = admin.database().ref("jobs");
return jobsRef
.child(jobTrack)
.once("value")
.then(jobs => {
const pendingUpdates = {}; // "path: value" pairs to be applied to the database
const feedsRef = admin.database().ref("feeds");
jobs.forEach(jobSnapshot => { // This is DataSnapshot#forEach
const job = jobSnapshot.val();
const percent = getMatchedPercent(candidate, job);
if (percent >= 0.9) {
const pushId = feedsRef.push().key; // push() without arguments doesn't write anything to the database, it just generates a new reference with a push ID we can use.
const path = job.feedId + "/upcomingWeek/" + pushId;
pendingUpdates[path] = candidate; // queue add to team's feed
}
});
// apply all updates in pendingUpdates object,
// relative to feedsRef as an all-or-nothing operation.
// e.g. pendingUpdates["feed001/upcomingWeek/9jksdfghsdjhn"] = "someUserId"
// will be written to "feeds/feed001/upcomingWeek/9jksdfghsdjhn"
return feedsRef.update(pendingUpdates); // commit changes
})
.catch(err => {
console.log("Failed to apply all feed updates: ", err);
});
});