NodeJS的sequelize的钩子

635 阅读2分钟

这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战

Hooks(生命周期事件)是在执行 sequelize 中的调用之前和之后调用的函数., 例如,如果要在保存之前始终在模型上设置一个值,则可以添加一个 beforeUpdate hook进行操作

连接 Hooks

Sequelize 提供了四个 hook,它们在获得或释放数据库连接之前和之后立即执行:

  • sequelize.beforeConnect(callback)

    • 回调具有以下形式 async (config) => /* ... */
  • sequelize.afterConnect(callback)

    • 回调具有以下形式 async (connection, config) => /* ... */
  • sequelize.beforeDisconnect(callback)

    • 回调具有以下形式 async (connection) => /* ... */
  • sequelize.afterDisconnect(callback)

    • 回调具有以下形式 async (connection) => /* ... */

如果需要异步获取数据库凭据,或者需要在创建低级数据库连接后直接访问它,例如,可以从令牌存储异步获取数据库密码,并使用新的凭证对 Sequelize 的配置对象进行更新:

这些 hook 只能声明为永久全局 hook,因为所有模型都共享连接池

sequelize.beforeConnect(async (config) => {
  config.password = await getAuthToken();
});

常见 Hooks 触发顺序

  1. beforeBulkCreate(instances, options), beforeBulkDestroy(options), beforeBulkUpdate(options)
  2. beforeValidate(instance, options)
  3. afterValidate(instance, options), validationFailed(instance, options, error)
  4. beforeCreate(instance, options), beforeDestroy(instance, options), beforeUpdate(instance, options), beforeSave(instance, options), beforeUpsert(values, options)
  5. afterCreate(instance, options), afterDestroy(instance, options), afterUpdate(instance, options), afterSave(instance, options), afterUpsert(created, options)
  6. afterBulkCreate(instances, options), afterBulkDestroy(options), afterBulkUpdate(options)

声明 Hooks

Hook 的参数通过引用传递, 相当于可以更改值, 这些出现在 insert / update 语句中, 一个 hook 可能包含异步动作 - 在这种情况下, hook 函数应该返回一个 Promise对象

// 方法 1 通过 .init() 方法
class User extends Model {}
User.init({
  username: DataTypes.STRING,
  mood: {
    type: DataTypes.ENUM,
    values: ['happy', 'sad', 'neutral']
  }
}, {
  hooks: {
    beforeValidate: (user, options) => {
      user.mood = 'happy';
    },
    afterValidate: (user, options) => {
      user.username = 'Toni';
    }
  },
  sequelize
});

// 方法 2 通过 .addHook() 方法
User.addHook('beforeValidate', (user, options) => {
  user.mood = 'happy';
});

User.addHook('afterValidate', 'someCustomName', (user, options) => {
  return Promise.reject(new Error("I'm afraid I can't let you do that!"));
});

// 方法 3 通过 direct 方法
User.beforeCreate(async (user, options) => {
  const hashedPassword = await hashPassword(user.password);
  user.password = hashedPassword;
});

User.afterValidate('myHookAfter', (user, options) => {
  user.username = 'Toni';
});

删除 hooks

只能删除带有名称参数的 hook. 同名的 hook 调用 .removeHook() 将删除所有对象

class Book extends Model {}
Book.init({
  title: DataTypes.STRING
}, { sequelize });

Book.addHook('afterCreate', 'notifyUsers', (book, options) => {
  // ...
});

Book.removeHook('afterCreate', 'notifyUsers');