【问题标题】:How do I prevent 'require' module cache executions in Node.js?如何防止 Node.js 中的“需要”模块缓存执行?
【发布时间】:2019-04-05 05:20:50
【问题描述】:

我一直在阅读,据我了解,require 自动执行并解析模块中的函数。

有什么办法可以防止这种情况发生吗?

用例很简单;为了防止自己拥有一个 50000902931 长行文件,我想将 MySql 函数移动到一个单独的模块(例如,db_functions)。

但是如果require 在启动时自动运行所有这些函数,并且再次 当我调用app.js 中的函数时,数据库信息将非常冗余。这是一个快速简单的示例 sn-p:

app.js

const express = require('express')
const db_functions = require('./db_functions')

app.get(/save_a_new_visit', (req, res, next) => {
   db_functions.saveAVisit
     .then(() => {
        res.sendStatus(200)
     }
}); 

db_functions.js

const knex = require('knex')

function saveAVisit(knex) {
    console.log('You are saving a new visit')

    const visit = {
       visits: new Date()
    }

    return knex('this_is_an_example').insert(visit)
}

当我运行我的服务器时,我的控制台会在启动时记录You are saving a new visit,然后当我访问/save_a_new_visit 端点时再次会这样做。

当然,我希望它只是在我访问访问页面时创建一个新访问。对?合乎逻辑的,我想。

这是第二个曲线球 - 这仅仅是因为我在本地开发吗?一旦项目放在 Heroku 或任何地方,这种双重写作会停止吗?任何帮助、提示或注释将不胜感激。

【问题讨论】:

  • 我想知道的第一件事是您当前从您的应用程序中看到的行为是什么? require 所做的唯一一件事就是将所有 require 引用解析到每个模块的底部,以便所有引用模块的初始版本仅加载一次。在应用程序逻辑执行这些功能之前,不会执行任何给定模块中定义的各个功能。所以我想知道您是否看到了一些奇怪的行为,或者只是担心根据您的研究发生的事情。
  • 我想我看到了奇怪的行为 - 引用的模块已加载,并且在加载时也执行。我不确定这是否是“奇怪”的行为(我对 Node.js 还很陌生,所以我认为事情就是这样)。当我启动我的服务器时,我所有的导出函数都在运行——只要我启动服务器。然后,当我导航到特定网页时,该功能再次运行。在应用程序调用中运行的函数有效,但该函数似乎也在简单的应用程序启动时运行。
  • 你没有在db_functions.js上导出任何东西
  • 对,对不起,忘了添加那行。我稍后会编辑它。

标签: javascript node.js express async-await knex.js


【解决方案1】:

我建议对您的代码进行一些更改,如下所示:

app.js

const app = require('express')
const db_functions = require('./db_functions')

app.get('/save_a_new_visit', (req, res, next) => {
    db_functions.saveAVisit()
      .then(() => {
          res.sendStatus(200)
          next()
      })
})

db_functions.js

const knex = require('knex')

module.exports.saveAVisit = async () => {
    console.log('You are saving a new visit')

    const visit = { visits: new Date() }

    return await knew('this_is_an_example').insert(visit)
}

app.js 代码中,我更改了您的 Express 模块导入变量的名称,以与您在这些导入语句下方的 RESTful 路由声明保持一致。此外,我在调用 saveAVisit() 函数的承诺链中添加了一个方法调用。我没有为此函数指定任何参数,因为实际上您不需要在该函数中定义任何参数,正如您在第二个代码 sn-p 中看到的那样。最后,我添加了对 next() 函数的调用,因为您将其包含在路由定义的参数列表中,如果您注意 next() 函数的段落,则应确保调用它。

在您的db_functions.js 代码中,我更改了您的函数定义以包含一个前缀,以便该函数实际上可用于任何尝试导入此模块的导入代码。其次,我使用async 关键字将函数定义为异步的。我这样做是为了在函数体中定义实际数据库接口逻辑时可以使用await 关键字。请查看asyncawait 文档以获取有关使用这两个特殊关键字的更多信息和示例。我还删除了您定义的函数参数,因为当您已经在模块定义的顶部导入它时,不需要传递 knex 模块的实例。最后,因为我假设 knex.insert() 函数是异步的,所以我在该调用之前添加了一个 await 关键字,以便代码在返回执行函数之前等待来自数据库的响应。

对代码进行这些更改应该会导致在模块导入时不再调用数据库代码。如果在进行这些更改后问题仍然存在,则可能是您的应用程序中存在您未在上面提供的其他代码导致此行为。如果是这样,请编辑您的帖子并添加该代码,以便我可以帮助您修复它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-21
    • 2011-02-24
    • 2016-04-11
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多