Try to transform bcrypt.hash callback into promise - javascript

In order to practice in JS, I'm trying to write the same code using a callback and a promise.
const bcrypt = require('bcrypt');
const saltRounds = 10;
const myPlaintextPassword = 'secret';
Callback version
function hashPassword(password, callback) {
bcrypt.hash(password, saltRounds, function(err, hash) {
if (err) {
return callback(err); // EDIT
}
return callback(null, hash); // EDIT
});
}
hashPassword(myPlaintextPassword, (err, hash) => {
if (err) {
return console.log(err);
}
return console.log(hash);
})
Promise version
async function hashPassword(password) {
return await bcrypt.hash(password, saltRounds);
}
hashPassword(myPlaintextPassword)
.then(res => console.log("result :", res))
.catch(err => console.log("error :", err));
Question : are these snippets "identical" (under the hood) ?
Thank you for your help.

Related

Returning undefined result after awaiting function

I am trying to get the result back from function where the result is in the callback. However the result always come back as undefined even though I set it to be the res. Can someone explain why this does not work?
function getData(id, callback) {
return dataModel.findOne({ id }).exec((err, res) => {
if (err) return callback(err)
return callback(null, res)
})
}
async function middleware(req.body) {
try {
let result
await getData(req.body, (err, res) => {
if (err) throw err
result = res
})
await nextFunc(result)... // result is undefined
} catch (err) {
console.log(err)
}
}
You are using callbacks, but in order to make things work with async await you are supposed to use promises
Try
function getData(id, callback) {
return new Promise((resolve, reject) => {
dataModel.findOne({ id }).exec((err, res) => {
if (err) reject(err);
resolve(res);
});
});
}
async function middleware(req.body) {
try {
let result = await getData(req.body);
await nextFunc(result);
} catch (err) {
console.log(err);
}
}

What is the syntax to using await and async in asynchronous functions using nodejs?

I am trying to create a basic API in nodejs to perform CRUD actions on a database.
I do not understand why the result is undefined
exports.getPlaylist = async function (req, res) {
console.log('Recieved getPlaylist request');
result = await connection.executeQuery('SELECT * from Users');
res.status(200).send(result);
console.log(result); // Logs undefined
};
This is the function that gets called and gets the data from the database:
async executeQuery(query) {
connection.query(query, function (err, result) {
if (err) {
console.log('Error executing query: ' + err);
}
console.log(result); // logs correct data
return result;
});
}
You need to "promisify" your callback. (see require('utils').promisify ) for a shorthand for applying to functions that follow node.js callback style (function(err,result){}).
executeQuery(query) {
return new Promise((res, rej) => {
connection.query(query, function (err, result) {
if (err) {
console.log('Error executing query: ' + err);
rej(err)
} else {
console.log(result); // logs correct data
res(result);
}
});
});
}
Now inside an async function you can await executeQuery(query)
The execute is not a promise base function, you cannot use await on a callback function.
change the execute function to promise base
Example:
executeQuery(query) {
return new Promise( (resolve, reject) => {
connection.query(query, function (err, result) {
if (err) {
console.log('Error executing query: ' + err);
reject('Error executing query: ' + err);
}
console.log(result); // logs correct data
resolve(result);
});
});
}
Add try catch in your calling function
exports.getPlaylist = async function (req, res) {
console.log('Recieved getPlaylist request');
try{
result = await connection.executeQuery('SELECT * from Users');
res.status(200).send(result);
console.log(result); // Logs undefined
} catch(error) {
console.log(error)
}
};

why is await not working even when used in async function

I made a function to search a user by email id. I'm calling that function in an async function using await and assigning the returned value to or constant/variable but getting undefined on printing the constant/variable
function search(email) {
sql = `SELECT email FROM users WHERE email = '${email}'`;
db.query(sql, (err, res) => {
if (err) {
console.log(err);
}
else {
return res[0].email;
}
})
}
const auth = async (req, res, next) => {
try {
const token = req.header('Authorization').replace('Bearer', '');
const decoded = jwt.verify(token, 'catisdoguniversaltruth');
const user = await search(decoded._id);
console.log(user);
if (!user) {
throw new Error();
}
next();
}
catch (e) {
res.status(401).send("Not Authenticated, Please login");
}
};
module.exports = auth;
You need search() to be a promise and not a function.
await waits for a promise to resolve.
Try this:
function search(email) {
return new Promise((resolve, reject) => {
sql = `SELECT email FROM users WHERE email = '${email}'`;
db.query(sql, (err, res) => {
if (err) {
reject(err);
}
else {
resolve(res[0].email);
}
})
})
}
This will be resolved as promise and auth() will wait.
You could also build search() as async/await promise. Doesn't really matter as long as you return a promise resolve.

Modular Implementation of MongoDB using Promises and Async/Await

I would like to make an Ajax request to my MongoDB server and use the data along with other async tasks using a standalone function so that I can modularize my code as much as possible. I am not very experienced with async programming so I might be doing some basic mistake. In my code, I used another function (doubleAfter2Seconds) returning a promise, which works fine. The result variable from await getMongoData("mydb", url) is outputted as undefined instead of the actual data.
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://{MyServer}:27017/";
function getMongoData(dboArg, urlArg) {
var myPromise = () => {
return new Promise(resolve => {
MongoClient.connect(urlArg, { useNewUrlParser: true }, function(err, db) {
if (err) throw err;
var dbo = db.db(dboArg);
dbo.collection(myCollection).find({}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
resolve(result[0]);
});
})
})
}
}
function doubleAfter2Seconds(x) {
return new Promise(resolve => {
console.log("v");
setTimeout(() => {
resolve(x * 2);
}, 1000);
});
}
async function addAsync(x) {
// This works
const a = await doubleAfter2Seconds(10);
console.log(a);
// This doesn't work
result = await getMongoData("mydb", url);
console.log(result);
return x;
}
addAsync(10).then((sum) => {
console.log(sum);
});
Here is the corrected getMongoData function based on the comments
function getMongoData(dboArg, urlArg) {
return new Promise(resolve => {
MongoClient.connect(urlArg, { useNewUrlParser: true }, function(err, db) {
if (err) throw err;
var dbo = db.db(dboArg);
dbo.collection(myCollection).find({}).toArray(function(err, data) {
err
? reject(err)
: resolve(data[0]);
});
})
})
}

Fetching all stripe customers with async await

I am trying to compile a list of all customers using the Stripe Node API. I need to make continual fetches 100 customers at a time. I believe that I need to use a Promise within the API call to use async await, but I can't for the life of me figure out where to put it. Hoping to make this gist public use and I want to get it right, thanks.
getAllCustomers()
function getMoreCustomers(customers, offset, moreCustomers, limit) {
if (moreCustomers) {
stripe.customers.list({limit, offset},
(err, res) => {
offset += res.data.length
moreCustomers = res.has_more
customers.push(res.data)
return getMoreCustomers(customers, offset, moreCustomers, limit)
}
)
}
return customers
}
async function getAllCustomers() {
const customers = await getMoreCustomers([], 0, true, 100)
const content = JSON.stringify(customers)
fs.writeFile("/data/stripe-customers.json", content, 'utf8', function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
}
IF res in stripe.customers.list({limit, offset}).then(res => ...) is the same as res in the "callback" version of stripe.customers.list({limit, offset}, (err, res) - then you probably could rewrite your code like
const getMoreCustomers = limit => {
const getThem = offset => stripe.customers.list({limit, offset})
.then(res => res.has_more ?
getThem(offset + res.data.length).then(result => res.data.concat(...result)) :
res.data
);
return getThem(0);
};
async function getAllCustomers() {
const customers = await getMoreCustomers(100);
const content = JSON.stringify(customers);
fs.writeFile("/data/stripe-customers.json", content, 'utf8', function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
}
additional to Jaromanda X's answer, it seems there is no offset option to customers api, but starting_after https://stripe.com/docs/api/node#list_customers
So, getMoreCustomers may be fixed like
const getMoreCustomers = starting_after => {
const getThem = starting_after => stripe.customers.list({limit: 100, starting_after: starting_after})
.then(res => res.has_more ?
getThem(res.data[res.data.length - 1]).then(result => res.data.concat(...result)) :
res.data
);
return getThem(starting_after);
};
async function getAllCustomers() {
const customers = await getMoreCustomers(null);
const content = JSON.stringify(customers);
fs.writeFile("/data/stripe-customers.json", content, 'utf8', function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
}

Categories