Load module in nodejs after setting DB data - node.js

My final goal is to have module.exports to contain some DB value which was loaded during app init
I have tried the following
module.exports = (async function() {
const cities = await internalUsage.aggregate(citiesPipeline);
console.log("HandleCities - Cities loaded")
return cities[0].cities;
})();
But that gives me a promise
Any idea on how to do that?
** Update **
For now I'm using globals, if anyone has a solution to keep this in the module, I would love to hear

Sadly this is not possible with only using module.exports. Due to the function being async the best thing you can get is a Promise when using vanilla NodeJS module.exports.
This is not that bad if you can await for it. module.exports works like a factory and only a single Promise will be generated no matter how many times you require it.
const citiesPromise = require('./XXXXX_XXXXX');
(async function(){
const cities = await citiesPromise();
...
});
An alternative solution is to abstract the NodeJS module using Dependency Injection (DI) with asynchronous factory support. This will allow you to export a Promise and get its value as an injection.
Not all NodeJS DI provides this abstraction for async values so be careful when selecting DI lib.
You can check InversifyJS although it encourage using TypeScript it has ES6 example as will https://github.com/inversify/InversifyJS/blob/master/wiki/basic_js_example.md.

Related

Jest mock knex fn.now(), but keep rest of implementation

I am writing tests for a service that uses knex, however, since the knex calls has several uses of knex.fn.now() my tests will produce varied results over time. I'm wondering if it's possible to mock/spy/hijack the inner calls to knex.fn.now() to something I can control, while letting the rest of the code stay in its 'real' implementation. I can only find examples of mocking knex completely which would make the purpose of my testing pointless.
So I'm wondering if it's possible to have jest listen for a specific function call and insert another value in it's stead.
You can mock Knex package by creating a folder __mocks__/knex/index.js.
Inside this file u can require the real knex implementation, change it, and export.
It should look something like this:
// __mocks__/knex/index.js
const knex = require('knex');
const fixedTime = new Date();
knex.fn.now = () => fixedTime;
module.exports = knex;

Is there any way to get data from the database without using async/await in Nest.js?

Is there any way to use callback function for getting the data from the database using typeorm in nest.js and process that data, after that I want to send a response.
I am not sure that I understood your question correctly, but out of the box, you can use TypeORM (assuming you use a SQL DB, Mongoose works similarly, though). The repository functions return a Promise<>, so you could use something like this (from the docs):
return this.photoRepository
.find()
.then(result => {//... your callback code goes here...
});
You could wrap this code in a function getModifiedResult(cb){} and pass the callback into it. Secondly, Remember that async/await is just syntactic sugar for promises, so the above is equivalent to:
result = await this.photoRepository.find();
cbAction = //... do something with your result here
return cbAction;
Again, you could just wrap this.
Another idea is to wrap the promise in an Observable, using the RxJS from operator (fromPromise for RxJS versions < 6). You can then put your callback into the subscription:
//... Note that this returns a subscription for you to unsubscribe.
return from(this.photoRepository
.find()
.then(result => result))
.subscribe(result => //... your callback code
);
If you go down that route, however, it may be worthwhile to modify your results using RxJS operators, like map, switchMap,....
You can just use the from/of operators from rxjs.
Example
create(user: UserInterface): Observable<UserInterface> {
return from(this.userRepository.save(newUser))
}
And if you want you can also pipe the outcome
create(user: UserInterface): Observable<UserInterface> {
return from(this.userRepository.save(user)).pipe(
map((user: UserInterface) => user))
)
}
The answer is that you can use observables and / or promises (async await). I often use an observable for the wrapper function and then promises for addition work in a pipe. I'm not sure why I don't use observables for everything but it doesn't matter.
TypeORM integrates nicely with Nestjs and the docs show how to do the basics. With Postgres there is a problem with arrays that I'm trying to figure out though. An SO post and a Github issue have gone unanswered.
It looks like TypeORM, along with most modern JS packages, have been built with only promises in mind. Callbacks are, for the most part, not used in many programs today unless absolutely necessary, as promises and async/await syntax make the code much cleaner and more readable than the possible callback hell you may enter when using callbacks. It does look like sequelize accepts callbacks, and there are some docs in the recipes section about how to use NestJS with Sequelize
This is not much to do with Nest itself, it's just how you write your code and handle whatever libraries you might have. Let's say you have your database fetching function with a callback:
function findUsersWithCallback(function callback() {
// do something with db
callback(err, results);
});
You can wrap this into a promise-like function with, say, util.promisify
const findUsersPromisified = require('util').promisify(findUsersWithCallback);
What's left is to use your standard Nest provider:
#Injectable() UsersService {
findUsers() {
return findUsersPromisified();
}
}
Now your UsersService behaves like the rest of the framework, and your old callback-based code is nicely wrapped so you can safely ignore it.

How to use properly promises in node.js project using classes?

(solution at the bottom)Project construction
I am converting a 'simple' node.js project into full object project node.js. I have found ressources to better organize my files but i still have a problem with classes. I have done php project in object, but the node JS structure seems to be particular.
I consulted :
Node Modular Architecture
How to correctly modularize a node.js project?
For what I understand :
app.js is my router from where I will define what controller I need to respond to the client request.
/routes is where I have my controllers where I instantiate my objects and use their methods.
project organization
My classes are in a folder at the root but I could move it to the public/javascript folder. My problem is about to confine application tier code in the classes that are supposed to access the database.
For exemple, only the class User has a method to update the user name in the database. So in my controlers (/routes) I dont want any sql queries (using sequelize by the way).
I don't know how to do
I tried to do a promise in the controller in which I call the class's method who does the query and return the result.
var user = new User();
var users = new Promise(function(resolve, reject) {
user.select();
});
Promise.all([users]).then(function(values){
console.log(values);
}
console.log(users);
)
In my class I do
models.user.findAll({
attributes: ['user_login','user_points','user_id']
}).then(
users => {
resolve(users);
}
)
Here as expected, resolve is not define. But if I put the resolve just after I call the class method like this:
var users = new Promise(function(resolve, reject) {
user.select();
resolve(result);
});
result is not defined and it will resolve without waiting for the query to be done.
Questions
As I am not experimented and dont find any detailed or recent topic on this subject I don't have any clue on how to proceed.
My first question is : does the problem could come from files organization (or more generaly is mine a usual/good practice).
My second question is how do I handle this type of structure with classes and node.js so my exemple should work.
Thank you for your help.
I will add that since I dont find recent topic on this subject I am verry interested in making a step by step guide to build a full object project in node.js with app/routes/classes and ES6 js. The objective is to better understand it and give it to my supervisor so he can correct it and use it for future recruits and publish it.
Solution
Thanks to #estus, I now unerstand that you can store a Promise in a variable.
It allow me to use a .then on this variable.
var result = a.select();
result.then(function(result) {
console.log('my result : ', result);
});
In the class you only return the result as you dont want to resolve the Sequelize promise :
users => {
return users;
}

How do you save the results of a mongoose query to a variable, so that its value can be used *later* in the code?

I know this question has been asked a few times, but none seem to answer the particular part of using the query results for later.
I also know the problem resides on the fact that queries are asynchronous, and perhaps this is the reason I cannot seem to find a satisfactory answer.
Here's what I'm trying to do:
I have a node project with several sections, each section with different content. These sections have individual properties, which I decided to store in a Model for later use.
So far (and for simplicity sake) I have the following schema:
const SectionSchema = new Schema({
name: String,
description: String
})
const Section = mongoose.model('Sections',SectionSchema)
I'd like to retrieve this data to be used in one of my layouts (a navigation header), so I tried something like this:
const express = require('express')
const app = express()
Section.find().then(function(docs){
app.locals.sections = docs
})
console.log(app.locals.sections) // undefined
This obviously doesn't quite work due to find() being asynchronous, or rather, it does work but the values are populated at a different time. I know that if I do the console.log check inside the function I'd get a result, but that's not the concern, I want to store the data in app.locals so that I could later use it in one of my layouts.
Ideally I'd like to load this data once, before the server begins to listen to requests.
Feel free to correct me if I've made any wrong assumptions, I'm very new to node, so I don't quite know how to approach things quite yet.
Thanks in advance.
EDIT: I should've mentioned I'm using express.
Your node app will likely be comprised of route handlers for http requests. app.locals.section will be undefined if you call it outside of the callback, but it will exist in the route handler.
Let's say you were using something like express or restify:
const app = restify.createServer()
app.get('/', (req, res) => {
return res.json(app.locals.sections)
})
Section.find().then(function(docs){
app.locals.sections = docs
})
console.log(app.locals.section) // is undefined
app.listen(8080-, ()=>{
console.log('Server started 🌎 ',8080)
})
Actually, it might be undefined if the database call took a long time and or a user hit the app super soon after startup. Starting the server in the callback would ensure app.locals.section existed under every scenario:
Section.find().then(function(docs){
app.locals.sections = docs
app.listen(8080-, ()=>{
console.log('Server started 🌎 ',8080)
})
})
You can use async/await within a function to make it seem like you aren't using promises. But you can't use it at the top level of your module. See here: How can I use async/await at the top level?
It really would be fairly idiomatic to do all your app startup in a promise chain. It's a style of coding you are going to see a lot of.
Section.find().then((docs)=>{app.locals.sections = docs})
.then (()=>{/*dosomething with app.locals.sections */})
.then(startServer)
function startServer() {app.listen(8080-, ()=>{
console.log('Server started 🌎 ',8080)
})}

Node.js // A module to manage a sqlite database

I managed to create a module to handle all the database call. It uses this lib: https://github.com/developmentseed/node-sqlite3
My issues are the following.
Everytime I make a call, I need to make sure the database exist, and if not to create it.
Plus, as all the calls are asynchronous, I end up having loads of functions in functions in callbacks ... etc.
It pretty much looks like this:
getUsers : function (callback){
var _aUsers = [];
var that = this;
this._setupDb(function(){
var db = that.db;
db.all("SELECT * FROM t_client", function(err, rows) {
rows.forEach(function (row) {
_aUsers.push({"cli_id":row.id,"cli_name":row.cli_name,"cli_path":row.cli_path});
});
callback(_aUsers);
});
});
},
So, is there any way I can export my module only when the database is ready and fully created if it does not exist yet?
Does anyone see a way around the "asynchronous" issue?
You could also try using promises or fibers ...
I don't think so. If you make it synchronous, you are taking away the advantage. Javascript functions are meant to be that way. Such a situation is referred to as callback hell. If you are facing problems managing callbacks then you can use these libraries :
underscore
async
See these guides to understand basics of asynchronous programming
Node.js: Style and structure
Using underscore.js managing-callback-spaghetti-in-nodejs
Using async.js node-js-async-programming

Resources