参数没有传递给Firebase云函数中的本地函数



我有一个火球云函数,如下所示:

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 = [];
jobs.forEach(job => {
promises.push(job.val());
});
return Promise.all(promises);
})
.then(jobs => {
return jobs.forEach(job => {
var percent = getMatchedPercent(candidate, job);
if (percent >= 0.9) {
admin
.database()
.ref("feeds")
.child(job.feedId)
.child("upcomingWeek")
.push(candidate); // add to team's feed
}
});
})
.catch(err => {
console.log("firebase got an error: ", err);
});
});

在函数foo中,我调用了一个本地非云函数getMatchedPercent,其定义如下:

const getMatchedPercent = (candidate, job) => {
console.log("In get percent: ", candidate, job);
// do something
};

问题是,当我在调用getMatchedPercent之前在foo中检查job.val()时,我可以看到从控制台打印的job.val()的有效数据。当我进入getMatchedPercent时,我试图打印job,它抱怨它是undefined

我错过了什么吗?为什么job的信息在调用函数时会丢失?谢谢

您的问题是由以下几行引起的:

const promises = [];
jobs.forEach(job => {
promises.push(job.val());
});
return Promise.all(promises);

job.val()返回一个(数据的(对象而不是promise,所以Promise.all()错误地将其解释为一个没有值的已解析promise。在您的下一个代码块中,数组jobsundefined值的数组,而不是您期望的数据。

要解决此问题,您应该返回值数组,而不是使用Promise.all()

const jobValues = [];
jobs.forEach(job => {
jobValues.push(job.val());
});
return jobValues;

但是,因为这里没有异步工作,所以您可以压平Promise链。通过这样做,您将使用更少的内存,因为您不需要一个同时包含所有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);
});
});

相关内容

  • 没有找到相关文章