I have a simple node module which connects to a database and has several functions to receive data, for example this function:
dbConnection.js:
import mysql from 'mysql'; const connection = mysql.createConnection({ host: 'localhost', user: 'user', password: 'password', database: 'db' }); export default { getUsers(callback) { connection.connect(() => { connection.query('SELECT * FROM Users', (err, result) => { if (!err){ callback(result); } }); }); } };
The module would be called this way from a different node module:
app.js:
import dbCon from './dbConnection.js'; dbCon.getUsers(console.log);
I would like to use promises instead of callbacks in order to return the data. So far I've read about nested promises in the following thread: Writing Clean Code With Nested Promises, but I couldn't find any solution that is simple enough for this use case. What would be the correct way to return result
using a promise?
If the callback function returns non-error output, we resolve the Promise with the output. Let's start by converting a callback to a promise for a function that accepts a fixed number of parameters: const fs = require('fs'); const readFile = (fileName, encoding) => { return new Promise((resolve, reject) => { fs.
They can handle multiple asynchronous operations easily and provide better error handling than callbacks and events. In other words also, we may say that, promises are the ideal choice for handling multiple callbacks at the same time, thus avoiding the undesired callback hell situation.
Callbacks are functions passed as arguments into other functions to make sure mandatory variables are available within the callback-function's scope. Promises are placeholder objects for data that's available in the future.
Promise
classI recommend to take a look at MDN's Promise docs which offer a good starting point for using Promises. Alternatively, I am sure there are many tutorials available online.:)
Note: Modern browsers already support ECMAScript 6 specification of Promises (see the MDN docs linked above) and I assume that you want to use the native implementation, without 3rd party libraries.
As for an actual example...
The basic principle works like this:
resolve
and reject
This might seem like a lot so here is an actual example.
exports.getUsers = function getUsers () { // Return the Promise right away, unless you really need to // do something before you create a new Promise, but usually // this can go into the function below return new Promise((resolve, reject) => { // reject and resolve are functions provided by the Promise // implementation. Call only one of them. // Do your logic here - you can do WTF you want.:) connection.query('SELECT * FROM Users', (err, result) => { // PS. Fail fast! Handle errors first, then move to the // important stuff (that's a good practice at least) if (err) { // Reject the Promise with an error return reject(err) } // Resolve (or fulfill) the promise with data return resolve(result) }) }) } // Usage: exports.getUsers() // Returns a Promise! .then(users => { // Do stuff with users }) .catch(err => { // handle errors })
In Node.js 7.6, the v8 JavaScript compiler was upgraded with async/await support. You can now declare functions as being async
, which means they automatically return a Promise
which is resolved when the async function completes execution. Inside this function, you can use the await
keyword to wait until another Promise resolves.
Here is an example:
exports.getUsers = async function getUsers() { // We are in an async function - this will return Promise // no matter what. // We can interact with other functions which return a // Promise very easily: const result = await connection.query('select * from users') // Interacting with callback-based APIs is a bit more // complicated but still very easy: const result2 = await new Promise((resolve, reject) => { connection.query('select * from users', (err, res) => { return void err ? reject(err) : resolve(res) }) }) // Returning a value will cause the promise to be resolved // with that value return result }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With