I node.js 如何更新已经需要的模块的值

I node.js how to update the value of an already required module

我距离使用 nodejs 的一个非常简单的数据库缓存系统只有一步之遥。我不想安装像 Redis 这样完整的数据处理解决方案,我只需要读取和缓存数据,有时从 DB 重新加载它,没有任何处理功能,所以我实现了这个:

我觉得我离成功还有一小步,这是我实现的(我 运行 node.js v14.15.1,我简化了所有代码以使其更具可读性.. .):

首先我让模块自己导出权限,它有效,当我需要模块时我得到了权限列表:

/** FILE cached_permissions.js **/        
const permissionModel = require("../models/permission.model")

getPermissionsAtInit = async () => {
  return await permissionModel.find().exec()
}
module.exports = getPermissionsAtInit()

那么,经典路由文件:

/** FILE permissions.route.js **/    

// Permission service
const PermissionService = require("../services/permission.service")

// Routes to get permissions from DB
app.get("/api/permissions", async (req, res) => { 
    res.send(await PermissionService.getPermissionsFromDB()} )

// Route to get permission from cache
app.get("/api/cached-permissions", async (req, res) => { 
    res.send(await PermissionService.getCachedPermissions()})

// Route to reset permission cache
app.get("/api/reset-cache", async (req, res) => { 
    await PermissionService.resetCache()
    res.send("cache reseted")})

这里是权限服务模块

/** FILE permission.service.js */
// Module with cached permissions
const cachedPermissions = require("./cached_permissions.js")

// Module to query the db
const permissionModel = require("../models/permission.model")

class PermissionService {

  static getPermissionsFromDB = async () => {
    // Mongoose query to get data from DB
    return await permissionModel.find().exec()
  }

  static getCachedPermissions = () => { 
    // Directly returns value from cached module
    return cachedPermissions 
  }

  static resetCache = async () => {
    // firstly we delete the cached module
    delete require.cache[require.resolve("./cached_permissions.js")]
    
    // then we require again the module to force the re-cache
    require("./cached_permissions.js")
  }
}

module.exports = PermissionService

所以我可以运行以下内容:

这么好,这是预期的行为

我知道 /api/reset-cache 已经完成,因为我 console.log Object.keys(require.cache),我可以看到它在 delete require.cache[...] 之后被删除,我可以看到它在 delete require.cache[...] 之后再次出现新 require("./cached_permissions.js").

但无论如何,当我再次调用/api/cached-permissions时,值并没有更新。感觉我的文件 permission.service.js 中的 const cachedPermissions = require("./cached_permissions.js") 只在服务器启动时被加载一次,而 permissions.route.js 文件需要 permission.service.js 文件,而不是每次路由都是调用,即使我重新加载特定模块。

你知道我可以在已经加载的文件中重新加载模块,或者在已经加载的文件中更新模块的值,或者其他一些方法来完成这项工作吗?我觉得我距离一个非常简单的数据库缓存系统只有一小步......

It feels like the const cachedPermissions = require("./cached_permissions.js") from my file permission.service.js has been loaded only once when the server starts, and not each time a route is called

嗯,这正是您编写代码的目的。 cachedPermissionspermission.service.js 模块中的 constant,您永远不会更新该常量。相反,如果你会做

static getCachedPermissions = () => { 
  // Directly returns value from cached module
  return require("./cached_permissions.js"); 
}

它会在每次请求时加载模块(从模块缓存中加载,或者评估模块代码是否新鲜)。


但实际上没有理由为此使用模块缓存。许可服务模块中的一个简单变量就足够了:

/* permission.service.js */

const permissionModel = require("../models/permission.model"); // Module to query the db

async function getPermissionsFromDB() {
  // Mongoose query to get data from DB
  return await permissionModel.find().exec()
}

let cachedPermissions = getPermissionsFromDB();

module.exports.getPermissionsFromDB = getPermissionsFromDB;

module.exports.getCachedPermissions = () => cachedPermissions;

module.exports.resetCache = () => {
  cachedPermissions = getPermissionsFromDB();
};