简体   繁体   中英

ReactJS + MongoDB + NodeJS/ExpressJS: What is process.nextTick(function() { throw err; });?

In my ReactJS project, I am currently running the server with NodeJS and ExpressJS, and connecting to the MongoDB using MongoClient. I have a login API endpoint set up that accepts a request with user's username and password. And if a user is not found, should catch the error and respond with an error ( status(500) ) to the front-end.

But rather than responding to the front-end with an json error, the server gets crashed. I have tried everything to figure out why but still no luck.

How can I fix the following error? Any guidance or insight would be greatly appreciated, and will upvote and accept the answer.

I intentionally made a request with a username and a password ( { username: 'iopsert', password: 'vser'} ) that does not exist in the database.

Here is the login endpoint:

//login endpoint
app.post('/api/login/', function(req, res) {
  console.log('Req body in login ', req.body)

  console.log('THIS IS WHAT WAS PASSED IN+++++', req._id)

  db.collection('users').findOne({username: req.body.username}, function(err, user) {
    console.log('User found ')

    if(err) {
      console.log('THIS IS ERROR RESPONSE')
      // Would like to send this json as an error response to the front-end 
      res.status(500).send({
        error: 'This is error response',
        success: false,
      })
    }

    if(user.password === req.body.password) {
      console.log('Username and password are correct')
      res.status(500).send({
        username: req.body.username,
        success: true,
        user: user,
      })
    } else {
      res.status(500).send({
        error: 'Credentials are wrong',
        success: false,
      })
    }
  })

And here is the terminal error log:

Req body in login  { username: 'iopsert', password: 'vset' }
THIS IS WHAT WAS PASSED IN+++++ undefined
User found 
/Users/John/practice-project/node_modules/mongodb/lib/utils.js:98
    process.nextTick(function() { throw err; });
                                  ^

TypeError: Cannot read property 'password' of null
    at /Users/John/practice-project/server/server.js:58:12
    at handleCallback (/Users/John/practice-project/node_modules/mongodb/lib/utils.js:96:12)
    at /Users/John/practice-project/node_modules/mongodb/lib/collection.js:1395:5
    at handleCallback (/Users/John/practice-project/node_modules/mongodb/lib/utils.js:96:12)
    at /Users/John/practice-project/node_modules/mongodb/lib/cursor.js:675:5
    at handleCallback (/Users/John/practice-project/node_modules/mongodb-core/lib/cursor.js:165:5)
    at setCursorNotified (/Users/John/practice-project/node_modules/mongodb-core/lib/cursor.js:505:3)
    at /Users/John/practice-project/node_modules/mongodb-core/lib/cursor.js:578:16
    at queryCallback (/Users/John/practice-project/node_modules/mongodb-core/lib/cursor.js:226:18)
    at /Users/John/practice-project/node_modules/mongodb-core/lib/connection/pool.js:430:18

And /Users/John/practice-project/node_modules/mongodb/lib/utils.js:98 is referring to the following:

var handleCallback = function(callback, err, value1, value2) {
  try {
    if(callback == null) return;
    if(value2) return callback(err, value1, value2);
    return callback(err, value1);
  } catch(err) {
    process.nextTick(function() { throw err; });
    return false;
  }

  return true;
}

EDIT

Here are everything that's being imported to the server:

"use strict"

var express = require('express');
var path = require('path');
var config = require('../webpack.config.js');
var webpack = require('webpack');
var webpackDevMiddleware = require('webpack-dev-middleware');
var webpackHotMiddleware = require('webpack-hot-middleware');
var bodyParser = require('body-parser');
var MongoClient = require('mongodb').MongoClient;
var ObjectId = require('mongodb').ObjectID;
const jwt = require('jsonwebtoken')

var app = express();
var db;

var compiler = webpack(config);

app.use(webpackDevMiddleware(compiler, {noInfo: true, publicPath: config.output.publicPath}));

app.use(webpackHotMiddleware(compiler));

app.use(express.static('dist'));

app.use(bodyParser.json());

And this is how the request is made and error is caught:

  loginUser(creds) {
    var request = {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(creds),
    }

    fetch(`http://localhost:3000/api/login`, request)
    .then(res => res.json())
    .then(user => {
      console.log(user);
      console.log('Successful')
    })
    .catch(err => {
      console.log('Error is', err)
    })
  },

It looks to me like the error is being thrown on this line because user is not defined.

if(user.password === req.body.password) {...}

Take a harder look at your console statements.

1. Req body in login  { username: 'iopsert', password: 'vset' }
2. THIS IS WHAT WAS PASSED IN+++++ undefined
3. User found 
4. /Users/John/practice-project/node_modules/mongodb/lib/utils.js:98
5. process.nextTick(function() { throw err; });
                              ^
6. TypeError: Cannot read property 'password' of null
7. at /Users/John/practice-project/server/server.js:58:12

Line 2 shows that req._id is undefined

Your User found statement is printed before you check if there is an error or if the user actually exists, so it isn't representative of there actually being a user.

Line 6 shows that the error is being thrown because you're trying to read a property of password from a null object.


I'd recommend modifying your login logic to look more like this:

//login endpoint
app.post('/api/login/', function(req, res) {
  console.log('Performing login with req.body=');
  console.log(JSON.stringify(req.body, null, 4));

  // check for username
  if (!req.body.username) {
    return res.status(401).send({message: 'No username'});
  }

  // find user with username
  db.collection('users').findOne({username: req.body.username}, function(err, user) {

    // handle error
    if(err) {
      console.log('Error finding user.');
      return res.status(500).send({message: 'Error finding user.'});
    }

    // check for user
    if (!user) {
      console.log('No user.');
      return res.status(500).send({message: 'No user.'});
    }
    console.log('User found.');

    // check password
    if(user.password !== req.body.password) {
      console.log('Wrong password.');
      return res.status(401).send({message: 'Wrong password.'});
    }

    // return user info
    return res.status(200).send(user);
  });

Some final thoughts:

  • Make sure to handle the error (if it exists) and check that user exists before proceeding.
  • Always include return in your return res.status(...).send(...) statements, otherwise the subsequent code will execute.
  • It's generally not a good idea to save passwords as simple strings. Work toward encrypting them. Look at passport or bcrypt .

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM