简体   繁体   English

参数未传递给 firebase 云函数中的本地函数

[英]Param didn't pass to local function in firebase cloud functions

I have a firebase cloud function as follows:我有一个 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);
      });
  });

In function foo , I call a local non-cloud function getMatchedPercent which is defined as below:在函数foo ,我调用了一个本地非云函数 getMatchedPercent ,其定义如下:

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

The problem is when I checked job.val() in foo before calling getMatchedPercent , I can see valid data got printed from console for job.val() .问题是当我在调用getMatchedPercent之前检查foo job.val()时,我可以看到从job.val()控制台打印的有效数据。 When once get in getMatchedPercent , I tried to print job , it complains it's undefined .一旦进入getMatchedPercent ,我尝试打印job ,它抱怨它是undefined

Is there anything I missed?有什么我错过的吗? Why the information of job can be lost during calling a function?为什么在调用函数时会丢失job的信息? Thanks!谢谢!

Your problem is caused by these lines:您的问题是由以下几行引起的:

const promises = [];

jobs.forEach(job => {
  promises.push(job.val());
});

return Promise.all(promises);

job.val() returns an object (of the data) not a promise, so Promise.all() incorrectly interprets it as a resolved promise with no value. job.val()返回一个(数据的)对象而不是承诺,因此Promise.all()错误地将其解释为没有价值的已解决承诺。 In your next block of code, the array jobs is an array of undefined values rather than the data you were expecting.在您的下一个代码块中,数组jobsundefined值的数组,而不是您期望的数据。

To fix this, you would instead return the array of values rather than using Promise.all() .为了解决这个问题,你应该返回值数组而不是使用Promise.all()

const jobValues = [];

jobs.forEach(job => {
  jobValues.push(job.val());
});

return jobValues;

But because no asyncronous work is taking place here you can flatten your Promise chain.但是因为这里没有发生异步工作,所以你可以扁平化你的 Promise 链。 By doing so, you will use less memory because you won't need an array containing of all of your job.val() objects at once.通过这样做,您将使用更少的内存,因为您不需要一次包含所有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);
      });
  });

However, this still has another problem where some of the feed updates may succeed and others may fail which leaves your database in an unknown state.但是,这仍然存在另一个问题,即某些提要更新可能会成功,而另一些可能会失败,从而使您的数据库处于未知状态。 So instead you might want to consider writing to the database atomically (all data is written, or nothing at all).因此,您可能需要考虑以原子方式写入数据库(写入所有数据,或者什么都不写入)。

This could be achieved using:这可以使用以下方法实现:

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);
      });
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM