Reputation: 93
The below google cloud function returns a null result.
Same code works fine with onRequest and returns data as expected. I want to use a callable function in order to easily send parameters to the function. Anybody knows what's wrong here?
const functions = require('firebase-functions');
const mysql = require('mysql');
exports.getUserData = functions.https.onCall((data, context) => {
const connectionName =
process.env.INSTANCE_CONNECTION_NAME || 'instance';
const dbUser = process.env.SQL_USER || 'root';
const dbPassword = process.env.SQL_PASSWORD || 'password';
const dbName = process.env.SQL_NAME || 'someDb';
const mysqlConfig = {
connectionLimit: 1,
user: dbUser,
password: dbPassword,
database: dbName,
};
if (process.env.NODE_ENV === 'production') {
mysqlConfig.socketPath = `/cloudsql/${connectionName}`;
}
let mysqlPool;
if (!mysqlPool) {
mysqlPool = mysql.createPool(mysqlConfig);
}
mysqlPool.query('SELECT * from table where id = 1', (err, results) => {
if (err) {
console.error(err);
} else {
data.send(JSON.stringify(results));
}
});
})
Upvotes: 1
Views: 838
Reputation: 99
You can also wrap you mysqljs/mysql with a promise.
return new Promise((resolve, reject) => {
if (!id) {
resolve({success: false, customer: null, msg: 'No id provided.'});
}
let connection = mysql.createConnection({
host: db.host,
user: db.user,
password: db.password,
database: db.database
});
connection.connect(function (err) {
if (err) {
resolve({success: false, customer: null, msg: err});
}
let sql = "SELECT * FROM customers WHERE uid = ?);"
let values = [id];
connection.query(sql, values, function (error, result) {
if (error) {
console.log(error);
return {success: false, customer: null, msg: error};
} else {
if (result.length) {
connection.destroy();
resolve({success: true, customer: customer});
} else {
connection.destroy();
resolve({success: false, customer: null, msg: 'No customer details'});
}
}
});
});
});
Upvotes: 0
Reputation: 83048
As you will see in the three videos about "JavaScript Promises" from the official Firebase video series (https://firebase.google.com/docs/functions/video-series/) you MUST return a Promise or a value in your Cloud Function, to indicate to the platform that it has completed.
The mysqljs/mysql
library you use does not return Promises, so one way is to use promise-mysql
, which "is a wrapper for mysqljs/mysql
that wraps function calls with Bluebird promises".
I've not tried it, but something along the following lines should do the trick:
const functions = require('firebase-functions');
const mysql = require('mysql');
const mysqlPromise =require('promise-mysql');
exports.getUserData = functions.https.onCall((data, context) => {
//.....
const connectionOptions = ...;
return mysqlPromise.createPool(connectionOptions) //you must return the Promises chain
.then(pool => {
return pool.query('SELECT * from table where id = 1')
})
.then(results => {
return(results: JSON.stringify(results));
//send back the response with return() not with data.send(), see the doc
})
.catch(error => {
//See the Callable Functions doc: https://firebase.google.com/docs/functions/callable#handle_errors_on_the_client
});
});
Upvotes: 5