DEV Community

[Comment from a deleted post]
Collapse
sargalias profile image
Spyros Argalias

Here's one example of where you could have asynchronous function.

Currently, you're using a mock database which you set up yourself. It works synchronously. However, most databases you would use in production projects would take a long time to respond. They would work asynchronously. They would have some API that allows you to wait for it asynchronously. Most likely, they'll return a promise.

For example, in the helper_data.js file, your db.get function might look like this in a real codebase:

db.get = function get(query, keys, subListing = global.listings) {
  logger_.log({level: 'info', message: 'get'});
  const dataPromise = myDatabase.find('somequery'); // myDatabase.find() would return a promise
  return dataPromise;
};
Enter fullscreen mode Exit fullscreen mode

In terms of the database code you have right now, an easy thing to do might be to: keep most of your code the same, but return a promise. For example:

db.get = function get(query, keys, subListing = global.listings) {
  logger_.log({level: 'info', message: 'get'});
  return Promise.resolve(lo.pick(lo(subListing).find(query), keys)); // just wrap the data you're returning already into a promise with this line. This simulates what a real database package would return
};
Enter fullscreen mode Exit fullscreen mode

Then, in functions that use that code, you would need to handle those promises.

For example, in routes/index.js:

router.get('/tag/:tag', function(req, res, next) {
  const tag = req.params.tag;
  db.toPublic() // returns a promise, so use .then to execute the remaining code
    .then(listings => {
        return db.fetchByTag(tag, listings);
    }) // also returns a promise, so use .then again
    .then(listings => {
        res.render('index', {
            title: tag,
            user: req.session.user,
            listings: listings,
            scripts: JSVersionMappings,
        });
    })
});

// or, alternative syntax with async await.
// This is equivalent to the above, but does the .then behind the scenes
// It doesn't work on older versions of Node, so be careful
router.get('/tag/:tag', async function(req, res, next) {
  const tag = req.params.tag;
  let listings = await db.toPublic();
  listings = await db.fetchByTag(tag, listings);
  res.render('index', {
    title: tag,
    user: req.session.user,
    listings: listings,
    scripts: JSVersionMappings,
  });
});
Enter fullscreen mode Exit fullscreen mode

Of course, if you change your mock database functions to use promises, you'll break the code that uses those database functions. You'll need to update all of it to handle the promises properly.

In a real codebase, you would start with everything asynchronous, so this wouldn't be a problem. Or, your database client would have both synchronous and asynchronous functions, so you could change them one-by-one in your code without breaking everything else.

Hope this helps.