请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

报错:UnhandledPromiseRejectionWarning

提示是在model/user.js报错:

(node:9716) UnhandledPromiseRejectionWarning: Error
    at Function.verifyEmailPassword (D:\study\island\app\model\user.js:14:13)
(node:9716) 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(). (rejection id: 1)
(node:9716) [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.

我断点调试,发现是没有捕获异常,导致。可是在全局全了异常捕获,但实际上是没有去执行,不知道是怎么回事,需要怎么解决。

下面是涉及到的主要代码:
api/v1/token.js

const Router = require('koa-router')
const { TokenValidator } = require('../../validators/validator')
const { loginType } = require('../../lib/enum')
const { User } = require('../../model/user')

const router = new Router({
  prefix: '/v1/token'
})

// 获取token
router.post('/', async ctx => {
  const v = await new TokenValidator().validate(ctx)
  // 根据不同type,来处理不同的登录方式
  const type = v.get('body.type')
  switch (type) {
    case loginType.USER_EMAIL:
      emailLogin(v.get('body.account'), v.get('body.secret'))
      break;
    case loginType.USER_MINI_PROGRAM:
      break;
    default:
      break;
  }
})

async function emailLogin(account, secret) {
  const user = await User.verifyEmailPassword(account, secret)
}

module.exports = router

model/user.js

const { Model, DataTypes } = require('sequelize')
const bcrypt = require('bcryptjs');

const { sequelize } = require('../../core/db')

class User extends Model {
  static async verifyEmailPassword(email, plainPassword) {
    const user = await User.findOne({
      where: {
        email
      }
    })
    if (!user) {
      throw new global.errs.AuthFailed('账号不存在');
    }

    const correct = bcrypt.compareSync(plainPassword, user.password)
    if (!correct) {
      throw new global.errs.AuthFailed('密码不正确')
    }
    return user
  }
 }

User.init(
  {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true,
    },
    nickname: DataTypes.STRING(128),
    email: {
      type: DataTypes.STRING(128),
      unique: true
    },
    password: {
      type: DataTypes.STRING,
      set(value) {
        const salt = bcrypt.genSaltSync(10); // 10: 盐的复杂度,数字越大,密码越复杂,计算成本也越高
        const psw = bcrypt.hashSync(value, salt)
        this.setDataValue('password', psw)
      }
    },
    openid: {
      type: DataTypes.STRING(64),
      unique: true
    }
  },
  { sequelize, tableName: 'user' }
)

// 将数据模型创建到数据库
sequelize.sync({
  // force: true
})

module.exports = { User }

validators/validator.js

const { LinValidator, Rule } = require('../../core/lin-validator-v2')
const { User } = require('../model/user')
const { loginType } = require('../lib/enum')

class PositiveIntegerValidator extends LinValidator {
  constructor() {
    super()
    this.id = [
      new Rule('isInt', '需要是正整数', {
        min: 1
      })
    ]
  }
}

class RegisterValidator extends LinValidator {
  // email password1, password2, nickname
  constructor() {
    super()
    this.email = [
      new Rule('isEmail', '不符合邮箱规范')
    ]
    this.password1 = [
      new Rule('isLength', '密码至少6位,最多32位', { min: 6, max: 32 }),
      new Rule('matches', '密码不符合规范', /^[\w]{6,32}$/)
    ];
    this.password2 = this.password1
    this.nickname = [
      new Rule('isLength', '昵称长度限制在4-32位', {min: 4, max: 128})
    ]
  }

  validatePassword(vals) {
    const { password1, password2 } = vals.body
    if (password1 !== password2) {
      throw new Error('密码输入不一致')
    }
  }

  async validateEmail(vals) {
    const { email } = vals.body
    const user = await User.findOne({
      where: {
        email
      }
    })
    if (user) {
      throw new Error('邮箱已存在')
    }
  }

}

class TokenValidator extends LinValidator {
  constructor() {
    super()
    this.account = [
      new Rule('isLength', '不符合账号规范', {min: 4, max: 32})
    ]
    this.secret = [
      new Rule('isOptional'),
      new Rule('isLength', '密码长度为6-32位', {min: 6, max: 32})
    ]
  }

  validateLoginType(vals) {
    const { type } = vals.body
    if (!type) {
      throw new Error('type是必须参数')
    }
    if (!loginType.isThisType(type)) {
      throw new Error('type参数不合法')
    }
  }
}

module.exports = {
  PositiveIntegerValidator,
  RegisterValidator,
  TokenValidator
};

core/http-exception.js

class HttpException extends Error {
  constructor(msg = '服务器异常', errorCode = 10000, code = 400) {
    super()
    this.msg = msg
    this.errorCode = errorCode
    this.code = code
  }
}

class ParameterException extends HttpException {
  constructor(msg = '参数错误', errorCode = 10000) {
    super()
    this.code = 400
    this.msg = msg
    this.errorCode = errorCode
  }
}

class Success extends HttpException {
  constructor(msg = 'ok', errorCode = 200) {
    super()
    this.code = 200
    this.msg = msg
    this.errorCode = errorCode
  }
}

class NotFound extends HttpException {
  constructor(msg = '资源未找到', errorCode = 404) {
    super()
    this.code = 404
    this.msg = msg
    this.errorCode = errorCode
  }
}

class AuthFailed extends HttpException {
  constructor(msg = '授权失败', errorCode) {
    super()
    this.code = 401
    this.msg = msg
    this.errorCode = errorCode
  }
}

module.exports = {
  HttpException,
  ParameterException,
  Success,
  NotFound,
  AuthFailed
};

lib/enum.js

const isThisType = function (val) {
  for (let key in this) {
    if (this[key] === val) {
      return true
    }
  }
  return false
}
const loginType = {
  USER_MINI_PROGRAM: 100,
  USER_EMAIL: 101,
  USER_MOBILE: 102,
  ADMIN_EMAIL: 300,
  isThisType
}


module.exports = {
  loginType
}

core/db.js

const { Sequelize, Model, DataTypes } = require('sequelize');
const { database, user, password, host, port } = require('../config/config').database
const sequelize = new Sequelize(database, user, password, {
  dialect: 'mysql',
  host,
  port,
  logging: true,
  timezone: '+08:00',
  define: {
    underscored: true,
    freezeTableName: false,
    timestamps: true,
    paranoid: true
  }
})

module.exports = {
  sequelize
};

正在回答 回答被采纳积分+3

1回答

提问者 qq_野火燎原_0 2020-03-12 09:43:04

后面通过调试,发现这个异常,只能通过一层层地往上抛,到api路由里才可能被全局异常中件件拦截到。

具体代码如下:

api/v1/token.js:

const Router = require('koa-router')
const { TokenValidator } = require('../../validators/validator')
const { loginType } = require('../../lib/enum')
const { User } = require('../../model/user')

const router = new Router({
  prefix: '/v1/token'
})

// 获取token
router.post('/', async ctx => {
  const v = await new TokenValidator().validate(ctx)
  // 根据不同type,来处理不同的登录方式
  const type = v.get('body.type')
  switch (type) {
    case loginType.USER_EMAIL:
      try {
        await emailLogin(v.get('body.account'), v.get('body.secret'))
      } catch (error) {
        throw new global.errs.AuthFailed(error);
      }

      break;
    case loginType.USER_MINI_PROGRAM:
      break;
    default:
      throw global.errs.ParameterException('没有相应的处理函数');
  }
})

async function emailLogin(account, secret) {
  try {
    const user = await User.verifyEmailPassword(account, secret)
  } catch (error) {
    throw error
  }
}

module.exports = router

model/user.js:

const { Model, DataTypes } = require('sequelize')
const bcrypt = require('bcryptjs');

const { sequelize } = require('../../core/db')

class User extends Model {
  static async verifyEmailPassword(email, plainPassword) {
    const user = await User.findOne({
      where: {
        email
      }
    })
    console.log(global.errs);
    if (!user) {
      throw new global.errs.AuthFailed('账号不存在')
    }

    const correct = bcrypt.compareSync(plainPassword, user.password)
    if (!correct) {
      throw new global.errs.AuthFailed('密码不正确');
    }
    return user
  }
 }

User.init(
  {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true,
    },
    nickname: DataTypes.STRING(128),
    email: {
      type: DataTypes.STRING(128),
      unique: true
    },
    password: {
      type: DataTypes.STRING,
      set(value) {
        const salt = bcrypt.genSaltSync(10); // 10: 盐的复杂度,数字越大,密码越复杂,计算成本也越高
        const psw = bcrypt.hashSync(value, salt)
        this.setDataValue('password', psw)
      }
    },
    openid: {
      type: DataTypes.STRING(64),
      unique: true
    }
  },
  { sequelize, tableName: 'user' }
)

// 将数据模型创建到数据库
sequelize.sync({
  // force: true
})

module.exports = { User }

想问问,这跟老师的写法是一样的,为什么会出现这种情况,有什么好的解决办法吗,这个问题困扰我一天了

1 回复 有任何疑惑可以回复我~
  • 7七月 #1
    这个代码肯定还是和课程不一样,多半是哪里没有 await。仔细检查下调试下
    回复 有任何疑惑可以回复我~ 2020-03-12 19:08:39
  • 同学你解决了吗?我的问题给你一模一样,可我也找不到解决方法?
    (node:3316) UnhandledPromiseRejectionWarning: Error
        at Function.verifyEmailPassword (C:\Users\JuctTr\Desktop\graduation_project\server\models\userModel.js:30:19)
        at <anonymous>
    (node:3316) 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(). (rejection id: 1)
    (node:3316) [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.
    回复 有任何疑惑可以回复我~ 2020-03-15 21:44:30
  • 出现错误的是这一段代码:
            if (!user) {
                throw new global.errors.AuthFailed('账号不存在')
            }
    好像说是这个异常没有被捕获
    回复 有任何疑惑可以回复我~ 2020-03-15 21:45:58
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号