mrquad mrquad - 3 years ago 167
Node.js Question

Coding the service layer with promises

I want to take out my CRUD Logic out of the routes and put it in a service layer.

So basically I want to call the service layer like that:

const service = require("../service/post")

router.post("/new", (req, res) => {
service.createPost(req.body.titel, req.body.description, req.body.tags, function(id){
console.log("Created post with id: " + id)
res.redirect("index")
})
})


In my
postService.js
file I have the following function:

function createPost(titel, description, tags, callback) {

const post = {
titel: titel,
description: description,
tags: tags,
createdAt: new Date(),
deleted: false,
}
console.log("Create Post: " + post.titel + " " + post.description + " " + post.tags + " " + post.createdAt + " " + post.deleted)

knex("posts").insert(post, "id").then(id => {
console.log(id)
callback(id[0])
})
}


Currently I am using a
callback
to handle this function.

Any suggestion how to use a more promise based style to return back the id, and the code in the router waits when the promise is finished?

Thank you for your replies!

Answer Source

In your example, you can get rid of your callback parameter and return the promise returned by knex

createPost(...) {
  ...
  return knex('posts').insert(post, "id");
}

Then in your route you can await the result

router.post('/new', async (req, res) => {
  const id = await service.createPost(...);
  console.log("Created post with id: " + id[0]);
  res.redirect("index");
});

Alternatively, if you want to pre-process the response from knex (as it returns an array) then you can return a new Promise

async createPost(...) {
  ...
  const result = await knex('posts').insert(...);
  return result[0];
}

FWIW I'd recommend the latter as it provides a clean separation between the layers.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download