Firebase functions promises not firing correctly












0















I'm having a hard time understanding promises in Firebase functions. I have a function that listens for new files in a storage bucket and then emails the user as well as sending them a Discord message. I'm getting inconsistent results and I'm pretty sure its to do with promises and callbacks being setup incorrectly.



exports.sendSetup = functions.storage.bucket('*the-bucket-id*').object().onFinalize((object) => {
// Get a URL for the new config file
console.log('New conf file: ' + object.name);
const { Storage } = require('@google-cloud/storage');

const storage = new Storage({
projectId: '*the-project-id*',
keyFilename: 'googleServiceAccountKey.json'
});
var bucket = storage.bucket('*the-bucket-name*');

const file = bucket.file(object.name);
console.log('Generating download url for file ' + object.name);
return file.getSignedUrl({
promptSaveAs: '*the-file-name*',
action: 'read',
expires: '03-09-2491'
}).then(signedUrls => {
var split = object.name.split("/");
var env = split[0];
var customer_id = split[1];
getCustomerDetails(customer_id, signedUrls[0], env);
});
});

function getCustomerDetails(customer_id, fileUrl, env) {
console.log('Retrieving customer details for customer id ' + customer_id + ' from Stripe');
var stripe = stripeLive;
if (env == 'test') {
stripe = stripeTest;
}

stripe.customers.retrieve(
customer_id,
function (err, customer) {
if (err == null) {
sendMail(fileUrl, customer.email, customer_id, customer.metadata.name);
console.log('discordId= ' + customer.metadata.discordId);
if (customer.metadata.discordId != 'undefined') {
sendDiscord(fileUrl, customer.metadata.discordId, customer.metadata.discordName);
}
console.log('Finished');
} else {
console.log(err);
}
}
);
}

function sendDiscord(fileUrl, discordId, discordName) {
console.log('Attempting to send a discord message to Discord id ' + discordId);
const Discord = require('discord.js');
const client = new Discord.Client();
client.login('*discord-api-key*');
client.once('ready', () => {
console.log('Discord client ready');
client.fetchUser(discordId)
.then((User) => {
console.log('Got Discord user object. Attempting to send message');
return User.send({
embed: {
color: 3447003,
fields: [
{
name: 'Hey ' + discordName + '!',
value: 'Below are the instructions to get you up and running'
},
{
name: '**Step 1**',
value: 'some instructions'
}
]
}
});
})
.catch((err) => {
console.log(err);
})
});
}

function sendMail(fileUrl, customer_email, customer_id, customer_name) {
console.log('customer_name in sendMail function = ' + customer_name);
var firstName = customer_name.substring(0, customer_name.indexOf(' '));
console.log(firstName);

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(*sendGridApiKey*);
sgMail.setSubstitutionWrappers('{{', '}}'); // Configure the substitution tag wrappers globally

const msg = {
to: customer_email,
subject: 'Welcome!',
from: {
email: 'noreply@example.com.au',
name: 'me'
},
text: 'Let's get you setup...',
html: '<p></p>',
templateId: '*template-id*',
substitutions: {
first_name: firstName,
file_url: fileUrl
},
};
console.log('Sending email to ' + customer_email + ' customer id:' + customer_id);
sgMail.send(msg);
}


I've read a heap of articles about promises and callbacks but can't seem to wrap my head around it. The "sendSetup" function actually returns OK but appears to stop right at the start of the getCustomerDetails function. Appreciate any assistance! I'm a bit lost!










share|improve this question























  • You're ignoring most of the promises returned by the various APIs that you're using here. You're also not doing anything about the Stripe API callback not even giving you a promise (you'll need to add custom promise there to "promisify" its callback, or figure out if it can give you a promise instead of a callback). All told, a lot of things going wrong here that need attention.

    – Doug Stevenson
    Jan 20 at 3:29













  • Well, yeah, that's sort of the point of my question.

    – brendanosborne
    Jan 20 at 3:35






  • 1





    If you're looking for someone to rewrite the function, that will be a difficult thing to ask, since it would require a tremendous amount of effort to test that it actually works the want you want it to work. My suggestion - keep learning more about promises, and study the APIs you're using. Watch this video series for info specific to Cloud Functions: firebase.google.com/docs/functions/video-series

    – Doug Stevenson
    Jan 20 at 3:37













  • Nope, not looking for a rewrite. Bit of direction and was hoping there was a key concept I was missing.

    – brendanosborne
    Jan 20 at 3:49






  • 1





    The key concept is that you need to return a promise that resolves only after ALL the async work in your function is complete. You can leave no promise dangling, else the work will likely not finish, and your function will appear silently broken.

    – Doug Stevenson
    Jan 20 at 3:56
















0















I'm having a hard time understanding promises in Firebase functions. I have a function that listens for new files in a storage bucket and then emails the user as well as sending them a Discord message. I'm getting inconsistent results and I'm pretty sure its to do with promises and callbacks being setup incorrectly.



exports.sendSetup = functions.storage.bucket('*the-bucket-id*').object().onFinalize((object) => {
// Get a URL for the new config file
console.log('New conf file: ' + object.name);
const { Storage } = require('@google-cloud/storage');

const storage = new Storage({
projectId: '*the-project-id*',
keyFilename: 'googleServiceAccountKey.json'
});
var bucket = storage.bucket('*the-bucket-name*');

const file = bucket.file(object.name);
console.log('Generating download url for file ' + object.name);
return file.getSignedUrl({
promptSaveAs: '*the-file-name*',
action: 'read',
expires: '03-09-2491'
}).then(signedUrls => {
var split = object.name.split("/");
var env = split[0];
var customer_id = split[1];
getCustomerDetails(customer_id, signedUrls[0], env);
});
});

function getCustomerDetails(customer_id, fileUrl, env) {
console.log('Retrieving customer details for customer id ' + customer_id + ' from Stripe');
var stripe = stripeLive;
if (env == 'test') {
stripe = stripeTest;
}

stripe.customers.retrieve(
customer_id,
function (err, customer) {
if (err == null) {
sendMail(fileUrl, customer.email, customer_id, customer.metadata.name);
console.log('discordId= ' + customer.metadata.discordId);
if (customer.metadata.discordId != 'undefined') {
sendDiscord(fileUrl, customer.metadata.discordId, customer.metadata.discordName);
}
console.log('Finished');
} else {
console.log(err);
}
}
);
}

function sendDiscord(fileUrl, discordId, discordName) {
console.log('Attempting to send a discord message to Discord id ' + discordId);
const Discord = require('discord.js');
const client = new Discord.Client();
client.login('*discord-api-key*');
client.once('ready', () => {
console.log('Discord client ready');
client.fetchUser(discordId)
.then((User) => {
console.log('Got Discord user object. Attempting to send message');
return User.send({
embed: {
color: 3447003,
fields: [
{
name: 'Hey ' + discordName + '!',
value: 'Below are the instructions to get you up and running'
},
{
name: '**Step 1**',
value: 'some instructions'
}
]
}
});
})
.catch((err) => {
console.log(err);
})
});
}

function sendMail(fileUrl, customer_email, customer_id, customer_name) {
console.log('customer_name in sendMail function = ' + customer_name);
var firstName = customer_name.substring(0, customer_name.indexOf(' '));
console.log(firstName);

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(*sendGridApiKey*);
sgMail.setSubstitutionWrappers('{{', '}}'); // Configure the substitution tag wrappers globally

const msg = {
to: customer_email,
subject: 'Welcome!',
from: {
email: 'noreply@example.com.au',
name: 'me'
},
text: 'Let's get you setup...',
html: '<p></p>',
templateId: '*template-id*',
substitutions: {
first_name: firstName,
file_url: fileUrl
},
};
console.log('Sending email to ' + customer_email + ' customer id:' + customer_id);
sgMail.send(msg);
}


I've read a heap of articles about promises and callbacks but can't seem to wrap my head around it. The "sendSetup" function actually returns OK but appears to stop right at the start of the getCustomerDetails function. Appreciate any assistance! I'm a bit lost!










share|improve this question























  • You're ignoring most of the promises returned by the various APIs that you're using here. You're also not doing anything about the Stripe API callback not even giving you a promise (you'll need to add custom promise there to "promisify" its callback, or figure out if it can give you a promise instead of a callback). All told, a lot of things going wrong here that need attention.

    – Doug Stevenson
    Jan 20 at 3:29













  • Well, yeah, that's sort of the point of my question.

    – brendanosborne
    Jan 20 at 3:35






  • 1





    If you're looking for someone to rewrite the function, that will be a difficult thing to ask, since it would require a tremendous amount of effort to test that it actually works the want you want it to work. My suggestion - keep learning more about promises, and study the APIs you're using. Watch this video series for info specific to Cloud Functions: firebase.google.com/docs/functions/video-series

    – Doug Stevenson
    Jan 20 at 3:37













  • Nope, not looking for a rewrite. Bit of direction and was hoping there was a key concept I was missing.

    – brendanosborne
    Jan 20 at 3:49






  • 1





    The key concept is that you need to return a promise that resolves only after ALL the async work in your function is complete. You can leave no promise dangling, else the work will likely not finish, and your function will appear silently broken.

    – Doug Stevenson
    Jan 20 at 3:56














0












0








0








I'm having a hard time understanding promises in Firebase functions. I have a function that listens for new files in a storage bucket and then emails the user as well as sending them a Discord message. I'm getting inconsistent results and I'm pretty sure its to do with promises and callbacks being setup incorrectly.



exports.sendSetup = functions.storage.bucket('*the-bucket-id*').object().onFinalize((object) => {
// Get a URL for the new config file
console.log('New conf file: ' + object.name);
const { Storage } = require('@google-cloud/storage');

const storage = new Storage({
projectId: '*the-project-id*',
keyFilename: 'googleServiceAccountKey.json'
});
var bucket = storage.bucket('*the-bucket-name*');

const file = bucket.file(object.name);
console.log('Generating download url for file ' + object.name);
return file.getSignedUrl({
promptSaveAs: '*the-file-name*',
action: 'read',
expires: '03-09-2491'
}).then(signedUrls => {
var split = object.name.split("/");
var env = split[0];
var customer_id = split[1];
getCustomerDetails(customer_id, signedUrls[0], env);
});
});

function getCustomerDetails(customer_id, fileUrl, env) {
console.log('Retrieving customer details for customer id ' + customer_id + ' from Stripe');
var stripe = stripeLive;
if (env == 'test') {
stripe = stripeTest;
}

stripe.customers.retrieve(
customer_id,
function (err, customer) {
if (err == null) {
sendMail(fileUrl, customer.email, customer_id, customer.metadata.name);
console.log('discordId= ' + customer.metadata.discordId);
if (customer.metadata.discordId != 'undefined') {
sendDiscord(fileUrl, customer.metadata.discordId, customer.metadata.discordName);
}
console.log('Finished');
} else {
console.log(err);
}
}
);
}

function sendDiscord(fileUrl, discordId, discordName) {
console.log('Attempting to send a discord message to Discord id ' + discordId);
const Discord = require('discord.js');
const client = new Discord.Client();
client.login('*discord-api-key*');
client.once('ready', () => {
console.log('Discord client ready');
client.fetchUser(discordId)
.then((User) => {
console.log('Got Discord user object. Attempting to send message');
return User.send({
embed: {
color: 3447003,
fields: [
{
name: 'Hey ' + discordName + '!',
value: 'Below are the instructions to get you up and running'
},
{
name: '**Step 1**',
value: 'some instructions'
}
]
}
});
})
.catch((err) => {
console.log(err);
})
});
}

function sendMail(fileUrl, customer_email, customer_id, customer_name) {
console.log('customer_name in sendMail function = ' + customer_name);
var firstName = customer_name.substring(0, customer_name.indexOf(' '));
console.log(firstName);

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(*sendGridApiKey*);
sgMail.setSubstitutionWrappers('{{', '}}'); // Configure the substitution tag wrappers globally

const msg = {
to: customer_email,
subject: 'Welcome!',
from: {
email: 'noreply@example.com.au',
name: 'me'
},
text: 'Let's get you setup...',
html: '<p></p>',
templateId: '*template-id*',
substitutions: {
first_name: firstName,
file_url: fileUrl
},
};
console.log('Sending email to ' + customer_email + ' customer id:' + customer_id);
sgMail.send(msg);
}


I've read a heap of articles about promises and callbacks but can't seem to wrap my head around it. The "sendSetup" function actually returns OK but appears to stop right at the start of the getCustomerDetails function. Appreciate any assistance! I'm a bit lost!










share|improve this question














I'm having a hard time understanding promises in Firebase functions. I have a function that listens for new files in a storage bucket and then emails the user as well as sending them a Discord message. I'm getting inconsistent results and I'm pretty sure its to do with promises and callbacks being setup incorrectly.



exports.sendSetup = functions.storage.bucket('*the-bucket-id*').object().onFinalize((object) => {
// Get a URL for the new config file
console.log('New conf file: ' + object.name);
const { Storage } = require('@google-cloud/storage');

const storage = new Storage({
projectId: '*the-project-id*',
keyFilename: 'googleServiceAccountKey.json'
});
var bucket = storage.bucket('*the-bucket-name*');

const file = bucket.file(object.name);
console.log('Generating download url for file ' + object.name);
return file.getSignedUrl({
promptSaveAs: '*the-file-name*',
action: 'read',
expires: '03-09-2491'
}).then(signedUrls => {
var split = object.name.split("/");
var env = split[0];
var customer_id = split[1];
getCustomerDetails(customer_id, signedUrls[0], env);
});
});

function getCustomerDetails(customer_id, fileUrl, env) {
console.log('Retrieving customer details for customer id ' + customer_id + ' from Stripe');
var stripe = stripeLive;
if (env == 'test') {
stripe = stripeTest;
}

stripe.customers.retrieve(
customer_id,
function (err, customer) {
if (err == null) {
sendMail(fileUrl, customer.email, customer_id, customer.metadata.name);
console.log('discordId= ' + customer.metadata.discordId);
if (customer.metadata.discordId != 'undefined') {
sendDiscord(fileUrl, customer.metadata.discordId, customer.metadata.discordName);
}
console.log('Finished');
} else {
console.log(err);
}
}
);
}

function sendDiscord(fileUrl, discordId, discordName) {
console.log('Attempting to send a discord message to Discord id ' + discordId);
const Discord = require('discord.js');
const client = new Discord.Client();
client.login('*discord-api-key*');
client.once('ready', () => {
console.log('Discord client ready');
client.fetchUser(discordId)
.then((User) => {
console.log('Got Discord user object. Attempting to send message');
return User.send({
embed: {
color: 3447003,
fields: [
{
name: 'Hey ' + discordName + '!',
value: 'Below are the instructions to get you up and running'
},
{
name: '**Step 1**',
value: 'some instructions'
}
]
}
});
})
.catch((err) => {
console.log(err);
})
});
}

function sendMail(fileUrl, customer_email, customer_id, customer_name) {
console.log('customer_name in sendMail function = ' + customer_name);
var firstName = customer_name.substring(0, customer_name.indexOf(' '));
console.log(firstName);

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(*sendGridApiKey*);
sgMail.setSubstitutionWrappers('{{', '}}'); // Configure the substitution tag wrappers globally

const msg = {
to: customer_email,
subject: 'Welcome!',
from: {
email: 'noreply@example.com.au',
name: 'me'
},
text: 'Let's get you setup...',
html: '<p></p>',
templateId: '*template-id*',
substitutions: {
first_name: firstName,
file_url: fileUrl
},
};
console.log('Sending email to ' + customer_email + ' customer id:' + customer_id);
sgMail.send(msg);
}


I've read a heap of articles about promises and callbacks but can't seem to wrap my head around it. The "sendSetup" function actually returns OK but appears to stop right at the start of the getCustomerDetails function. Appreciate any assistance! I'm a bit lost!







node.js firebase google-cloud-functions






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 20 at 3:08









brendanosbornebrendanosborne

14811




14811













  • You're ignoring most of the promises returned by the various APIs that you're using here. You're also not doing anything about the Stripe API callback not even giving you a promise (you'll need to add custom promise there to "promisify" its callback, or figure out if it can give you a promise instead of a callback). All told, a lot of things going wrong here that need attention.

    – Doug Stevenson
    Jan 20 at 3:29













  • Well, yeah, that's sort of the point of my question.

    – brendanosborne
    Jan 20 at 3:35






  • 1





    If you're looking for someone to rewrite the function, that will be a difficult thing to ask, since it would require a tremendous amount of effort to test that it actually works the want you want it to work. My suggestion - keep learning more about promises, and study the APIs you're using. Watch this video series for info specific to Cloud Functions: firebase.google.com/docs/functions/video-series

    – Doug Stevenson
    Jan 20 at 3:37













  • Nope, not looking for a rewrite. Bit of direction and was hoping there was a key concept I was missing.

    – brendanosborne
    Jan 20 at 3:49






  • 1





    The key concept is that you need to return a promise that resolves only after ALL the async work in your function is complete. You can leave no promise dangling, else the work will likely not finish, and your function will appear silently broken.

    – Doug Stevenson
    Jan 20 at 3:56



















  • You're ignoring most of the promises returned by the various APIs that you're using here. You're also not doing anything about the Stripe API callback not even giving you a promise (you'll need to add custom promise there to "promisify" its callback, or figure out if it can give you a promise instead of a callback). All told, a lot of things going wrong here that need attention.

    – Doug Stevenson
    Jan 20 at 3:29













  • Well, yeah, that's sort of the point of my question.

    – brendanosborne
    Jan 20 at 3:35






  • 1





    If you're looking for someone to rewrite the function, that will be a difficult thing to ask, since it would require a tremendous amount of effort to test that it actually works the want you want it to work. My suggestion - keep learning more about promises, and study the APIs you're using. Watch this video series for info specific to Cloud Functions: firebase.google.com/docs/functions/video-series

    – Doug Stevenson
    Jan 20 at 3:37













  • Nope, not looking for a rewrite. Bit of direction and was hoping there was a key concept I was missing.

    – brendanosborne
    Jan 20 at 3:49






  • 1





    The key concept is that you need to return a promise that resolves only after ALL the async work in your function is complete. You can leave no promise dangling, else the work will likely not finish, and your function will appear silently broken.

    – Doug Stevenson
    Jan 20 at 3:56

















You're ignoring most of the promises returned by the various APIs that you're using here. You're also not doing anything about the Stripe API callback not even giving you a promise (you'll need to add custom promise there to "promisify" its callback, or figure out if it can give you a promise instead of a callback). All told, a lot of things going wrong here that need attention.

– Doug Stevenson
Jan 20 at 3:29







You're ignoring most of the promises returned by the various APIs that you're using here. You're also not doing anything about the Stripe API callback not even giving you a promise (you'll need to add custom promise there to "promisify" its callback, or figure out if it can give you a promise instead of a callback). All told, a lot of things going wrong here that need attention.

– Doug Stevenson
Jan 20 at 3:29















Well, yeah, that's sort of the point of my question.

– brendanosborne
Jan 20 at 3:35





Well, yeah, that's sort of the point of my question.

– brendanosborne
Jan 20 at 3:35




1




1





If you're looking for someone to rewrite the function, that will be a difficult thing to ask, since it would require a tremendous amount of effort to test that it actually works the want you want it to work. My suggestion - keep learning more about promises, and study the APIs you're using. Watch this video series for info specific to Cloud Functions: firebase.google.com/docs/functions/video-series

– Doug Stevenson
Jan 20 at 3:37







If you're looking for someone to rewrite the function, that will be a difficult thing to ask, since it would require a tremendous amount of effort to test that it actually works the want you want it to work. My suggestion - keep learning more about promises, and study the APIs you're using. Watch this video series for info specific to Cloud Functions: firebase.google.com/docs/functions/video-series

– Doug Stevenson
Jan 20 at 3:37















Nope, not looking for a rewrite. Bit of direction and was hoping there was a key concept I was missing.

– brendanosborne
Jan 20 at 3:49





Nope, not looking for a rewrite. Bit of direction and was hoping there was a key concept I was missing.

– brendanosborne
Jan 20 at 3:49




1




1





The key concept is that you need to return a promise that resolves only after ALL the async work in your function is complete. You can leave no promise dangling, else the work will likely not finish, and your function will appear silently broken.

– Doug Stevenson
Jan 20 at 3:56





The key concept is that you need to return a promise that resolves only after ALL the async work in your function is complete. You can leave no promise dangling, else the work will likely not finish, and your function will appear silently broken.

– Doug Stevenson
Jan 20 at 3:56












0






active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54273262%2ffirebase-functions-promises-not-firing-correctly%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54273262%2ffirebase-functions-promises-not-firing-correctly%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Callistus III

Ostreoida

Plistias Cous