Firebase functions promises not firing correctly
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
|
show 1 more comment
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
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
|
show 1 more comment
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
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
node.js firebase google-cloud-functions
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
|
show 1 more comment
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
|
show 1 more comment
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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