Saya sedang membuat aplikasi web sederhana yang menangani permintaan dan berkomunikasi dengan SQL db menggunakan Express dan Sequelize. Saat ini saya mengalami masalah saat memanggil fungsi async pada suatu objek, bagian this dari objek tersebut adalah undefined. Saya membungkus fungsi di express-async-handler untuk menangani pengembalian janji, anehnya jika saya menghapus pembungkus handler pada metode async saya dapat mengakses this tetapi seperti yang diharapkan tidak menangani kesalahan dengan benar. Apa yang saya salah pahami/lakukan? Di bawah ini adalah kode:

userController.js

var models  = require('../models');
const asyncHandler = require('express-async-handler')

var user = models.User

exports.registerUser = asyncHandler(async function(req, res) {
  var username = req.body.username,
      password = req.body.password;
      u = user.build({
        username: username, password: password
      })
  
      await u.registerUser()
      res.send('hello world')
  }
);

pengguna.js tidak berfungsi

const bcrypt = require('bcrypt');
const asyncHandler = require('express-async-handler')

module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    id: {
      type: DataTypes.UUID,
      defaultValue: sequelize.literal('uuid_generate_v4()'),
      primaryKey: true
    },
    name: DataTypes.STRING,
    username: DataTypes.STRING,
    password: DataTypes.STRING,
  }, {
    paranoid: true,
  });

  // Associations
  User.associate = function(models) {
    // associations can be defined here
    User.hasMany(models.Cat, {
      foreignKey: 'userId',
      as: 'cats',
      onDelete: 'CASCADE',
    })
  };

  // Instance methods
  User.prototype.registerUser = asyncHandler(async function () {
    await bcrypt.hash(this.password, 10, (err, hash) => {  // not able to access 'this'
      if(err) throw err;

      // Set the hashed password and save the model
      this.password = hash;
      this.save()
    });
  })
};

user.js menghapus asyncHandler() berfungsi

const bcrypt = require('bcrypt');
const asyncHandler = require('express-async-handler')

module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    id: {
      type: DataTypes.UUID,
      defaultValue: sequelize.literal('uuid_generate_v4()'),
      primaryKey: true
    },
    name: DataTypes.STRING,
    username: DataTypes.STRING,
    password: DataTypes.STRING,
  }, {
    paranoid: true,
  });

  // Associations
  User.associate = function(models) {
    // associations can be defined here
    User.hasMany(models.Cat, {
      foreignKey: 'userId',
      as: 'cats',
      onDelete: 'CASCADE',
    })
  };

  // Instance methods
  User.prototype.registerUser = async function () {
    await bcrypt.hash(this.password, 10, (err, hash) => {
      if(err) throw err;

      // Set the hashed password and save the model
      this.password = hash;
      this.save()
    });
  }
};
2
walshbm15 30 Juni 2020, 18:31

1 menjawab

Jawaban Terbaik

Saya membungkus fungsi di express-async-handler untuk menangani pengembalian janji

Tidak, Anda tidak perlu melakukan itu. Janji yang dikembalikan oleh metode User.prototype.registerUser Anda ditangani dengan baik dengan baris

await u.registerUser()

Anda hanya memerlukan pembungkus asyncHandler pada penangan rute Ekspres, yang tidak tahu cara menangani janji yang dikembalikan oleh async function.

Jika saya menghapus pembungkus handler pada metode async, saya dapat mengakses this, tetapi seperti yang diharapkan tidak menangani kesalahan dengan benar.

asyncHandler juga tidak membantu menangani kesalahan itu. Masalahnya adalah Anda melakukannya

if(err) throw err;

Di dalam panggilan balik asinkron, yang hanya merupakan pengecualian yang tidak tertangani yang membuat aplikasi Anda mogok. Sebagai gantinya, Anda harus menjanjikan bcrypt.hash sehingga Anda mendapatkan janji yang akan ditolak. Atau cukup gunakan versi janji:

User.prototype.registerUser = async function () {
  const hash = await bcrypt.hash(this.password, 10)
  this.password = hash;
  await this.save()
};
2
Bergi 30 Juni 2020, 16:52