Express JS 'this' undefined after routing with app.get(..)

express, javascript, node-mysql, node.js

Solution

You need to properly bind the function.

app.get('/v1/group', group.getAll);

only passes the `getAll` function as a handler, but the function itself has no concept of `this`. `this` is decided based on the context that is bound, or based on how the function is called. This blog post is useful for understanding how function context works.

app.get('/v1/group', group.getAll.bind(group));

Problem

I have a basic Node JS server which is designed to be used as an API, I've created a log and database module and I've started adding other modules to deal with different request types. I'm using Express.js and node-mysql When I visit `/v1/group` I get the following error - ``` TypeError: Cannot read property 'database' of undefined at Group.getAll (C:\code\javascript\node\api\api\v1\groups.js:12:23) at callbacks (C:\code\javascript\node\api\node_modules\express\lib\router\index.js:161:37) ... ``` So I guess after recieving a request and calling `group.getAll()` that `this` is undefined but I don't understand why, is there a way to set `this` or have I structured my application all wrong? sever.js ``` "use strict"; var Express = require('express'); var Log = require('./database/log'); var Database = require('./database/database'); var dbConfig = require('./dbconfig.json'); var Group = require('./api/v1/groups'); //Init express var app = new Express(); //Init log and database var log = new Log(); var database = new Database(dbConfig, log); var initCallback = function() { //Init routes var group = new Group(database, log); //Group routes app.get('/v1/group', group.getAll); app.get('/v1/group/:id', group.getByID); app.listen(3000); log.logMessage("INFO", "Listening on port 3000"); }; //Test database connection database.getConnection(function(err, connection) { if (err) { log.logMessage("FATAL", "Error connecting to database, check database is running and the dbconfig.json file is present and correct."); process.exit(1); } connection.end(); initCallback(); }); ``` database.js ``` "use strict"; var mysql = require('mysql'); var Database = function(dbConfig, log) { this.connected = false; this.log = log; this.log.logMessage("INFO", "Connecting to database with: Host - " + dbConfig.dbhost + ", Database port - " + dbConfig.dbport + ", Database name - " + dbConfig.dbname + ", User " + dbConfig.dbuser + ", Password length - " + dbConfig.dbpass.length); this.pool = mysql.createPool({ host : dbConfig.dbhost, user : dbConfig.dbuser, port: dbConfig.dbport, password : dbConfig.dbpass, database: dbConfig.dbname }); }; Database.prototype.getConnection = function() { var args = arguments; return this.pool.getConnection.apply(this.pool, arguments); }; module.exports = Database; ``` groups.js ``` "use strict"; var Group = function(database, log) { this.database = database; this.log = log; }; Group.prototype.getAll = function(req, res) { console.log(this); // --> undefined var query = 'SELECT * FROM invgroups WHERE published = 1'; this.database.getConnection(function(err, connection) { // --> error line if (err) { res.send(500, "Database error"); } connection.query(query, function(err, results) { if (err) { res.send(500, "Database error"); } res.send(results); }); connection.end(); }); }; Group.prototype.getByID = function(req, res) { console.log(this); res.send({name: "Group Item 1"}); }; module.exports = Group; ```

Original source