【问题标题】:ReactJS + MongoDB + NodeJS/ExpressJS: What is process.nextTick(function() { throw err; });?ReactJS + MongoDB + NodeJS/ExpressJS:什么是 process.nextTick(function() { throw err; });?
【发布时间】:2017-02-23 01:49:32
【问题描述】:

在我的 ReactJS 项目中,我目前正在使用 NodeJS 和 ExpressJS 运行服务器,并使用 MongoClient 连接到 MongoDB。我设置了一个登录 API 端点,它接受带有用户用户名和密码的请求。如果未找到用户,则应捕获错误并向前端响应错误 (status(500))。

但不是以 json 错误响应前端,而是服务器崩溃了。我已经尝试了一切来找出原因,但仍然没有运气。

如何解决以下错误?任何指导或见解将不胜感激,并将投票并接受答案。

我故意使用数据库中不存在的用户名和密码 ({ username: 'iopsert', password: 'vser'}) 发出请求。

这里是登录端点:

//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,
      })
    }
  })

这里是终端错误日志:

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

/Users/John/practice-project/node_modules/mongodb/lib/utils.js:98 指的是以下内容:

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;
}

编辑

以下是要导入服务器的所有内容:

"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());

这就是发出请求和捕获错误的方式:

  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)
    })
  },

【问题讨论】:

  • 似乎 userreq.body 未定义,您是否在项目中包含 bodyParser
  • @adeneo 是的,请查看原帖中的编辑。当我使用存在的用户名和密码传入请求时,会记录正确的userreq.body,然后输入 if 语句。

标签: javascript node.js mongodb express reactjs


【解决方案1】:

在我看来,由于未定义 user,因此该行上出现了错误。

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

仔细查看您的控制台语句。

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

第 2 行显示 req._id 是 undefined

您的User found 语句在您检查是否存在错误或用户是否实际存在之前打印,因此它不代表实际存在用户。

第 6 行显示,由于您试图从空对象中读取 password 的属性,因此引发了错误。


我建议修改您的登录逻辑,使其看起来更像这样:

//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);
  });

一些最后的想法:

  • 确保处理错误(如果存在)并检查user 是否存在,然后再继续。
  • 始终在您的return res.status(...).send(...) 语句中包含return,否则将执行后续代码。
  • 将密码保存为简单字符串通常不是一个好主意。努力加密它们。查看passportbcrypt

希望这会有所帮助。

【讨论】:

  • 对不起,但实际上 req._id 只是不存在,因为请求没有传递它,所以忽略它。如果用户确实存在于数据库中,也不会发生刻度错误,所以我假设当找不到用户时,它没有正确处理错误响应?另外,当我执行 findOne() 并进入该函数时,这不是已经找到了用户名吗?再次检查用户有什么需要,不应该是user.username吗?为什么是!user,因为那个对象没有usernamepassword?感谢您的帮助
  • 刚刚试了一下,但错误返回实际上是作为response 从前端和控制台记录对象({message: "No user"}) 传入的,而不是被catch() 函数捕获作为error。我是否会在 catch() 函数中遗漏一些从前端捕获的东西?
  • 只是看看你是否看过我的最后一个 cmets。请告诉我。
猜你喜欢
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
  • 2017-11-19
相关资源
最近更新 更多