kriskowal / q

A promise library for JavaScript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Internal q TypeError on node-express server

jQrgen opened this issue · comments

Hello

I'm using q in my express-node server.

For some reason q crases with a TypeError when I GET the endpoint GET_nearbyTesters.

There is no stack trance from q to within my project, the stack trace ends in the q library folder

 /app/node_modules/q/q.js:155
                 throw e;
                 ^
 
 TypeError: Cannot read property 'app' of undefined
     at json (/app/node_modules/express/lib/response.js:246:17)
     at _rejected (/app/node_modules/q/q.js:864:24)
     at /app/node_modules/q/q.js:890:30
     at Promise.when (/app/node_modules/q/q.js:1142:31)
     at Promise.promise.promiseDispatch (/app/node_modules/q/q.js:808:41)
     at /app/node_modules/q/q.js:624:44
     at runSingle (/app/node_modules/q/q.js:137:13)
     at flush (/app/node_modules/q/q.js:125:13)
     at _combinedTickCallback (internal/process/next_tick.js:73:7)
     at process._tickCallback (internal/process/next_tick.js:104:9)

Route that triggers the crash (GET_nearbyTesters):

const router			= require('express').Router();
const middleware	= require('../middleware.js');


router.get('/', function (req, res, next) {
	middleware.getUsers(req)
		.then(function () {
			next();
		})
		.catch(res.json)
		.done();
}, function(req, res, next) {
	middleware.getNearbyUsers(req, res)
	.then(function () {
		next();
	})
	.catch(res.json)
	.done();
});

module.exports = router;

Middleware for the GET_nearbyTesters route

const calculate 		= require('./services/calculate.js');
const Q 						= require('q');
const firebase 			= require('firebase-admin');
const isDefined			= require('./services/calculate').isDefined;
const ref 					= firebase.database().ref();

const middleware = {
	// Binds usersSnap to req object
	getUsers: (req) => {
		const deferred = Q.defer();
		ref.child('users').once('value')
		.then((usersSnap) => {
			req.usersSnap = usersSnap;
			deferred.resolve(usersSnap.val());
		})
		.catch((error) => {
			deferred.reject(error);
		});

		return deferred.promise;
	},
	// Requires usersSnap being bound to req object.
	getNearbyTesters: function (req, res) {
		const deferred = Q.defer();
		const usersSnap = req.usersSnap;
		const userID = req.query.userID;
		const centerUser = usersSnap.child(userID);
		const nearbyTesters = [];
		let distance;

		if(isDefined(usersSnap)){
			usersSnap.forEach((userSnap) => {
				if(centerUser.key !== userSnap.key && userSnap.val().testMode){
					try {
						distance = calculate.distance(userSnap.val().lat, userSnap.val().long, centerUser.val().lat, centerUser.val().long, 'K');
					} catch(error){
						deferred.reject(error);
					}
					if(distance <= 1000){
						nearbyTesters.push(userSnap.val().facebook.uid);
					}
				}
			});
			res.type('json');
			res.status(200).json({ nearbyTesters: nearbyTesters });
			deferred.resolve(nearbyTesters);
			res.end();
		}else {
			deferred.reject(new Error('req.usersSnap is undefined'));
		}

		return deferred.promise;
	}
};

index.js just in case:

var	app            		= require('express')(),
	bodyParser     			= require('body-parser'),
	path           			= require('path'),
	serviceAccount 			= require(path.resolve(__dirname, process.env.firebase_service_account_path)),
	firebaseAdmin  			= require('firebase-admin');

firebaseAdmin.initializeApp({
	credential: firebaseAdmin.credential.cert(serviceAccount),
	databaseURL: process.env.firebase_url
});

// Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.json() );
app.use(bodyParser.urlencoded({ extended: false }));

app.use(function (req, res, next) {
	res.setHeader('Access-Control-Allow-Origin', '*');
	res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
	res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
	res.setHeader('Access-Control-Allow-Credentials', true);
	next();
});

app.use('/GET_nearbyUsers', require('./routes/GET_nearbyUsers.js'));
app.use('/GET_nearbyTesters', require('./routes/GET_nearbyTesters.js')); // The route in question
app.use('/POST_sendVerifySMS', require('./routes/POST_sendVerifySMS.js'));
app.use('/POST_backgroundLocation', require('./routes/POST_backgroundLocation.js'));

app.use(function (error, req, res, next) { // eslint-disable-line
	console.error(error);
	res.status(500).send(error);
});

// Start node server
app.set('port', (process.env.PORT || 1339 || 2000));
app.listen(app.get('port'), () => {
	console.log('Node app is running on port', app.get('port'));
});

require('./firebase-observers.js').init();

package.json just in case:

{
  "name": "flare_sms",
  "version": "1.0.0",
  "main": "app/index.js",
  "dependencies": {
    "body-parser": "1.17.1",
    "express": "4.15.2",
    "firebase": "^4.2.0",
    "firebase-admin": "^5.1.0",
    "q": "^1.5.0",
    "speakeasy": "2.0.0",
    "twilio": "^2.11.1",
    "util": "^0.10.3"
  },
  "devDependencies": {
    "chai": "^4.1.1",
    "chai-as-promised": "^7.1.1",
    "eslint": "^3.17.1",
    "eslint-plugin-mocha": "^4.11.0",
    "express-mocks-http": "0.0.11",
    "firebase-mock": "^1.1.5",
    "foreman": "^2.0.0",
    "istanbul": "^0.4.5",
    "mocha": "^3.5.0",
    "node-mocks-http": "^1.6.4",
    "nodemon": "^1.11.0",
    "nyc": "^11.1.0",
    "proxyquire": "^1.8.0",
    "supertest": "^3.0.0",
    "tap-spec": "^4.1.1"
  },
  "scripts": {
    "test": "./node_modules/.bin/mocha -w",
    "test-api": "node test/index.tutorial | tap-spec",
    "start": "nf start",
    "watch": "foreman run nodemon --watch ./"
  },
  "engines": {
    "node": "6.11.1"
  },
  "author": "Flare"
}

Thanks for any help.

The issue seems to be unrelated to q and instead related to error handling in my node-express server.