I have a use case where I need to run multiple tasks in series. Each task is required to perform some database operations. In my code step_1
, step_2
and step_3
are these task which get executed in series (Async Waterfall)
Following is my code
const config = require('config.json');
var mysql = require('mysql');
var async = require("async");
const pool = mysql.createPool({
host: config.database.dbhost,
user: config.database.dbuser,
password: config.database.dbpassword,
database: config.database.dbname
});
exports.handler = (event, context, callback) => {
pool.getConnection((err, connection) => {
if (err) throw new Error("Unable to get connection " + JSON.stringify(err));
async.waterfall([
step_1,
step_2,
step_3
], function (err, result) {
if(err){
throw new Error("something went south : "+ JSON.stringify(err));
}else{
connection.release();
callback(null, "SUCCESS: " + JSON.stringify(result));
}
});
function step_1(cb){
connection.query("step 1 query", function (error, response) {
if (error){
cb(null,error,null);
}
let id=result.insertId;
cb(null,null,id);
});
}
function step_2(error,id,cb){
if(error){
cb(null,error);
}else{
connection.query("step 2 query",,function (err,result){
if (err){
connection.query("error logging query",
function(er,result){
if (er) cb(null,er,null);
});
cb(null,err,null);
}
cb(null,null, id, result);
});
}
}
function step_3(error, id,result,cb){
if(error){
cb(error,null);
}else{
connection.query("step 3 query",function(err,result){
if (err) cb(err,null);
cb(null,result);
});
}
}
});
};
Although I have used a library to avoid nesting callbacks within callbacks, it still feels like bit callback-ish. Is there a better way to achieve my use case? Anything I can improve in my code, any suggestions please.
I have only included relevant parts of code, kindly let me know if any additional information is required.
1 Answer 1
A couple of helper functions will aid in flattening your callback chain:
function getConnection() {
return new Promise((res, rej) => {
pool.getConnection(function (err, connection) {
if (err) {
rej(err);
} else {
res(connection);
}
});
});
}
function query(connection, sql, params) {
return new Promise((res, rej) => {
connection.query(sql, params, function (err, rows) {
if (err) {
rej(err);
} else {
res(rows);
}
});
});
}
Then you can do something like:
async function step_1(connection) {
const rows = await query(connection, 'step 1 query');
return rows.insertId;
}
function step_2(connection, id) {
return query(connection, 'step 2 query', id);
}
function step_3(connection, id, result) {
return query(connection, 'step 3 query', id, result);
}
exports.handler = async (event) => {
const connection = await getConnection();
try {
const id = await step_1(connection);
const rows = await step_2(connection, id);
const result = await step_3(connection, id, rows);
return JSON.stringify(result);
} finally {
connection.release();
}
};
-
1\$\begingroup\$ Welcome to Code Review, answers that merely provide an alternate solution with no explanation or justification do not constitute valid Code Review answers and may be deleted. To avoid this possibility you can check how to answer. \$\endgroup\$dariosicily– dariosicily2020年06月22日 10:01:04 +00:00Commented Jun 22, 2020 at 10:01
-
\$\begingroup\$ Thank you for your time. returning promises and using them with await is quite useful +1 for that. \$\endgroup\$Dakait– Dakait2020年06月22日 22:13:36 +00:00Commented Jun 22, 2020 at 22:13
Explore related questions
See similar questions with these tags.