简体   繁体   中英

Properly chaining functions in Firebase function

I am building a function in Firebase Cloud Functions, which can utilize Node.js modules.

I am still new to the use of .then() and I'm struggling to figure out a way to chain my 3 functions webhookSend() , emailSendgrid() , and removeSubmissionProcessor() that happen right after the 'count' is incremented (the if statement that checks temp_shouldSendWebhook ). The whole idea of returning promises still confuses me a little, especially when it it involves external libraries.

const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp();

const request = require('request');

const firebaseConfig = JSON.parse(process.env.FIREBASE_CONFIG);
const SENDGRID_API_KEY = firebaseConfig.sendgrid.key;
const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(SENDGRID_API_KEY);

exports.submissionProcess = functions.database.ref('/submissions/processor/{submissionId}').onWrite((change, context) => {
  var temp_metaSubmissionCount = 0; // omitted part of function correctly sets the count
  var temp_shouldSendWebhook = true; // omitted part of function correctly sets the boolean

  return admin.database().ref('/submissions/saved/'+'testuser'+'/'+'meta').child('count')
    .set(temp_metaSubmissionCount + 1)
    .then(() => {

      // here is where im stuck
      if (temp_shouldSendWebhook) {
        webhookSend();
        emailSendgrid();
        removeSubmissionProcessor();
      } else {
        emailSendgrid();
        removeSubmissionProcessor();
      }

    })
    .catch(() => {
      console.error("Error updating count")
    });

});

function emailSendgrid() {
  const user = 'test@example.com'
  const name = 'Test name'

  const msg = {
      to: user,
      from: 'hello@angularfirebase.com',
      subject:  'New Follower',
      // text: `Hey ${toName}. You have a new follower!!! `,
      // html: `<strong>Hey ${toName}. You have a new follower!!!</strong>`,

      // custom templates
      templateId: 'your-template-id-1234',
      substitutionWrappers: ['{{', '}}'],
      substitutions: {
        name: name
        // and other custom properties here
      }
  };
  return sgMail.send(msg)
}

function webhookSend() {
  request.post(
    {
      url: 'URLHERE',
      form: {test: "value"}
    },
    function (err, httpResponse, body) {
      console.log('REQUEST RESPONSE', err, body);
    }
  );
}

function removeSubmissionProcessor() {
  admin.database().ref('/submissions/processor').child('submissionkey').remove();
}

I want to be able to construct the 3 functions to be called one after another such that they will all execute.

In order to chain these functions, they each need to return a promise. When they do, you can call them sequentially like this:

return webhookSend()
  .then(() => {
    return emailSendgrid();
  })
  .then(() => {
    return removeSubmissionProcessor();
  });

Or in parallel like this:

return Promise.all([webhookSend, emailSendgrid, removeSubmissionProcessor]);

Now, to make your functions return promises:

emailSendgrid : It looks like this returns a promise (assuming sgMail.send(msg) returns a promise), so you shouldn't need to change this.

removeSubmissionProcessor : This calls a function that returns a promise, but doesn't return that promise. In other words it fires off an async call ( admin.database....remove() ) but doesn't wait for the response. If you add return before that call, this should work.

webhookSend calls a function that takes a callback, so you'll either need to use fetch (which is promise-based) instead of request , or you'll need to convert it to return a promise in order to chain it:

function webhookSend() {
  return new Promise((resolve, reject) => {
    request.post(
      {
        url: 'URLHERE',
        form: {test: "value"}
      },
      function (err, httpResponse, body) {
        console.log('REQUEST RESPONSE', err, body);
        if (err) {
          reject(err);
        } else {
          resolve(body);
        }
      }
    );
  });
}

Use async functions and then you can use .then() or await before every function calls

for reference read this

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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