When developing an API using nodeJS and express, 2 js file involved as below
When I pm2 start main.js, doSth() in api.js works as I expected, however, when I pm2 stop main.js,
cleanSth() not working, anyone can advise how can I achieved my expected result (cleanSth when I pm2 stop)?
api.js
const express = require('express')
doSth()
const routes = (app) => { ... ... }
process.on('beforeExit', cleanSth()})
module.exports = routes
main.js
const express = require('express') const app = express()
const a = require('./api.js') a(app)
As stated in docs https://nodejs.org/api/process.html#process_event_beforeexit
The 'beforeExit' event is not emitted for conditions causing explicit termination, such as calling process.exit() or uncaught exceptions.
So if you only do some synchronous work in cleanSth then use exit event instead of beforeExit
Or you may want to have a look at this answer https://stackoverflow.com/a/64028857/3284355
Related
I've been following along with a PERN stack tutorial from YouTube and I've started running into problems with using the require function in the index file for my server application running Node v 17.7.2 with Express 4.17.
The code that's throwing the errors is here:
const express = require("express");
const app = express();
const cors = require("cors");
const routes = require("./routes/jwtAuth")
app.use(express.json());
app.use(cors());
app.use('/auth', myRoutes);
app.get('/', (req, res) =>{
res.send('hello world!');
});
app.listen(process.env.PORT, ()=>
console.log('listening at port 3000'),
);
The error I get is:
const express = require("express");
^
ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/Users/Nizz0k/Sites/pgpengapi/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
From what I've read this error used to be limited to using require() in frontend code, but after Node v14 can happen in server scripts as well. I have the type set to module. The error seems to be relatively recent, as I've not had any crashing changes when using require in the app up to now.
When you use ES modules (ie. when you set type to module), you need to use the import syntax:
import express from 'express';
I'm unit-testing some code of mine in nodejs that works with express.
While it seems obvious, I want to test that my routes are calling the right handler functions.
I'm using jest to create a mock function for the handler function.
While I successfully tried to test that a function is called inside another function, I cannot seem to test that a function (handler) is called from express get of post.
Let's see an examplee:
fruits.js
function orange (req,res,next) {res.status(200)} ;
module.exports = {orange}
app.js
const fruits = require('./fruits')
const express = require('express');
const app = express();
app.get('/fruits', fruits.orange);
module.exports = { app };
When I'm trying to test (with jest) that GET request (with the help of axios module) to /fruits is calling orange(), altough actually orange() works, it won't be saved as a calling with a mock function cover of spy cover.
How can I test that orange() has been called from the GET request ?
Try using supertest with Jest
const app = require('../app') //path to app.js
const request = require('supertest')
test('Upload Info Endpoint', async() => {
await request(app).get('/fruits')
.expect(resp.body.field).toMatch(mocked_field_value)
});
Dumb/Newb question...
I am learning/working on an API in Node / Express4 and I would like to break my routes out into another module. I have it working with the following code, but it seems awkward to me to keep re-using the require('express') statement... Is there a way to move more of the code from the routes.js file into server.js and still keep my .get and .post statements in the routes module? Thanks in advance!
server.js:
'use strict';
var express = require('express');
var routes = require('./routes');
var app = express();
app.use('/api', routes);
app.listen(3000, function() {
console.log('Listening);
});
routes.js
var express = require('express'); // how do I get rid of this line?
var router = express.Router(); // can I move this to server.js?
var apiRoute = router.route('');
apiRoute.get(function (req, res) {
res.send('api GET request received');
});
module.exports = router;
Your on the right track. Its actually cool to reuse the var express = require('express'); statement each time you need it. Importing, ( requiring ), modules is a cornerstone of modular development and allows you to maintain a separation of concerns with in the files of your project.
As far as modularly adding routes is concerned: The issue is that routes.js is misleading.
In order to modularly separate out your routes you should use several modules named <yourResource>.js. Those modules would contain all of the routing code as well as any other configuration or necessary functions. Then you would attach them in app.js with:
var apiRoute = router.route('/api');
apiRoute.use('/<yourResource', yourResourceRouter);
For example, if you had a resource bikes:
In app.js or even a module api.js:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes');
apiRoute.use('/bikes', bikeRoutes);
Then in bike.js:
var express = require('express');
var router = express.Router();
var bikeRoutes = router.route('/');
bikeRoutes.get(function (req, res) {
res.send('api GET request received');
});
module.exports = bikeRoutes;
From there its easy to see that you can build many different resources and continually nest them.
I have a file where I call all the require modules called 'app.js'
var express = require('express');
...
var app = express();
...
var routes = require('ruotes/index.js)
use('/', routes);
module.exports = app;
I call the index.js where I have all the routes
routes/index.js
var express = require('express');
var app = express();
/* import controllers */
var indexController = require('../controllers/index');
app.route('/')
.get(indexController.index);
module.exports = app;
The problem is I have two variables called app and I call twice express(). Does it exist a more elegant way to handle this situation? Maybe I could call the variable in router file in another way?
You are currently using a technique that is known as submounting.
If you want to avoid creating different instances of Express, you will have to pass your unique instance of Express as a parameter to your router, meaning that your index.js needs to export a function that accepts your app as a parameter.
Something like :
//=== routes/index.js
/* import controllers */
var indexController = require('../controllers/index');
module.exports = function(app){
app.route('/').get(indexController.index);
};
Doing so will allow you to keep the same instance of Express in your entire Web App.
Since you exported a function in index.js, you need to call it in app.js.
var express = require('express');
...
var app = express();
...
var routes = require('routes/index.js)(app)
module.exports = app;
You can use the same technique for routes, modules, models etc...
This technique will allow you to avoid re-requiring modules, and instantiating them, but you will need to write extra-bits to make sure your variables are passed from one side of your app to the other. Because of this, some prefer using the submounting technique, and requiring modules only where they are needed.
From koajs.com:
app.callback()
Return a callback function suitable for the http.createServer() method to handle a request. You may also use this callback function to mount your koa app in a Connect/Express app.
Now I have an Express app that already starts its own http server. How can I mount a koa app on top of this existing server, so that it shares the same port?
Would I include the koa app as an Express middlware? Do I still use app.callback() for that?
expressapp.use(koaapp.callback()) is fine. but remember, koaapp.callback() does not have a next, so there's no passing errors to the express app or skipping the koaapp once you use it.
it's better to keep them completely separate since their APIs are incompatible
var koaapp = koa()
var expressapp = express()
http.createServer(req, res) {
if (true) koaapp(req, res);
else expressapp(req, res);
})
Since you need a server instance in order to mount a middleware on a specific /prefix, it would be something like
var http = require('http');
var expressApp = require('express');
var koaApp = require('koa');
// ...
expressApp.use('/prefix', http.createServer(koaApp.callback()));