首页 > 解决方案 > NODE / UPDATE / API / SEQUELIZE:UnhandledPromiseRejectionWarning:TypeError:无法读取null的属性“电子邮件”

问题描述

编辑: 问题正是在身份验证中(实际上它工作正常,但是,令牌指的是数据库中旧用户的 ID):

   const { email, oldPassword } = req.body;

   const user = await User.findByPk(req.userId);

   if (email !== user.email) {
     const userExists = await User.findOne({ where: { email } });

     if (userExists) {
       return res.status(400).send({ error: 'User already exists.' });
     }
   }

可能,在我手动更改数据库后,令牌无法识别这一点。(我也设置了 7 天的有效期)

编辑 /\

错误:

Executing (default): SELECT "id", "name", "email", "password_hash", "provider", "created_at" AS "createdAt", "updated_at" AS "updatedAt" FROM "users" AS "User" WHERE "User"."id" = 7;
(node:1616) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'email' of null
    at update (C:\Project\src\app\controllers\UserController.js:56:24)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:1616) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate 
the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:1616) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

PS: WHERE "User"."id" = 7;

(在这种情况下,用户数据库中的 ID 为 = 1)

这条线代表

at update (C:\Project\src\app\controllers\UserController.js:56:24)

UserController 上的这部分代码:

if (email !== user.email) {   // <<<---- Here
      const userExists = await User.findOne({ where: { email } });

      if (userExists) {
        return res.status(400).send({ error: 'User already exists.' });
      }
    }

理解问题:

我正在 Node.js 中创建一个 API,我正在尝试进行用户更新

我正在使用Docker在数据库中使用sequelize(PostgreSQL)(我自己作为初学者,我考虑过Docker/Database/Sequelize有问题的可能性,因为我创建了10个假用户并将其插入到数据库中,之后,我删除了所有(手动,在 Postbird 上),当然第一个新的 user_ID 会变成,例如 11)。然后,我创建了一个新的数据库,并使用 id1 正常创建了用户。

我认为用户只有在通过以下身份验证时才能更新他的信息:( routes.use(authMiddleware);在 ./src/routes.js 中)

这是项目的架构:

./src/routes.js

import { Router } from 'express';

import UserController from './app/controllers/UserController';

import authMiddleware from './app/middlwares/auth';

const routes = new Router();

routes.use(authMiddleware);

routes.put('/users', UserController.update);

export default routes;

.src/app/controllers/UserController.js

import User from '../models/User';

class UserController {
  async update(req, res) {
    const { email, oldPassword } = req.body;

    const user = await User.findByPk(req.userId);

    if (email !== user.email) {
      const userExists = await User.findOne({ where: { email } });

      if (userExists) {
        return res.status(400).send({ error: 'User already exists.' });
      }
    }

    if (oldPassword && !(await user.checkPassword(oldPassword))) {
      return res.status(401).json({ error: 'Password does not match' });
    }

    const { id, name, provider } = await user.update(req.body);

    return res.json({
      id,
      name,
      email,
      provider,
    });
  }
}

export default new UserController();

./src/app/models/User.js

import Sequelize, { Model } from 'sequelize';
import bcrypt from 'bcryptjs';

class User extends Model {
  static init(sequelize) {
    super.init(
      {
        name: Sequelize.STRING,
        email: Sequelize.STRING,
        password: Sequelize.VIRTUAL,
        password_hash: Sequelize.STRING,
        provider: Sequelize.BOOLEAN,
      },
      {
        sequelize,
      }
    );

    this.addHook('beforeSave', async (user) => {
      if (user.password) {
        user.password_hash = await bcrypt.hash(user.password, 8);
      }
    });

    return this;
  }

  checkPassword(password) {
    return bcrypt.compare(password, this.password_hash);
  }
}

export default User;

./src/database/migrations/number-create-users.js

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('users', {
      id: {
        type: Sequelize.INTEGER,
        allowNulll: false,
        autoIncrement: true,
        primaryKey: true,
      },
      name: {
        type: Sequelize.STRING,
        allowNulll: false,
      },
      email: {
        type: Sequelize.STRING,
        allowNulll: false,
        unique: true,
      },
      password_hash: {
        type: Sequelize.STRING,
        allowNulll: false,
      },
      provider: {
        type: Sequelize.BOOLEAN,
        defaultValue: false,
        allowNulll: false,
      },
      created_at: {
        type: Sequelize.DATE,
        allowNulll: false,
      },
      updated_at: {
        type: Sequelize.DATE,
        allowNulll: false,
      },
    });
  },

  down: async (queryInterface) => {
    await queryInterface.dropTable('users');
  },
};

HTTP/PUT JSON 数据:

{
    "name": "user000",
    "email": "email000@domain.com.br",
    "oldPassword": "password000",
    "password": "123456",
    "confirmPassword": "123456"
}

考虑到用户已经通过身份验证。

标签: node.jsapinullsequelize.jsput

解决方案


问题可能是以下查询未找到用户。因此user可能是 undefined。你确定这条线是正确的吗?

    const user = await User.findByPk(req.userId);

并且userId不应该在请求的正文中或在params?IE:

    const user = await User.findByPk(req.params.userId);

如果用户 ID 在参数中,我认为您还需要将您的更新route为:

routes.put('/users/:userId', UserController.update);

此外,我认为将异步内容包装到 try catch 块中是一种很好的做法。像这样的东西:

try {

 const user = await User.findByPk(req.params.userId);

} catch (err) {

console.log(err)

}


推荐阅读