NodeJS module.exports在值初始化之前导出,async问题

gmxoilav  于 2023-04-20  发布在  Node.js
关注(0)|答案(1)|浏览(204)

我有一个关于module.exports的性质的问题,我试图用postgres,express和node构建一个简单的todo应用程序。
这是我的index.js

const express = require("express");
   const cors = require("cors");
   const pool = require("./db");
   const app = express();
   const PORT = 5000;

   app.use(cors());
   app.use(express.json());
   console.log("2");
   app.get("/todos", async (req, res) => {
   try {
    const result = await pool.query("SELECT * FROM todo");
    res.json(result.rows);
  } catch (err) {
    console.log(err);
  }
});

这是我的db.js

const fs = require("fs").promises;
const path = require("path");
const pgtools = require("pgtools");
const { Pool } = require("pg");
const dB = "perntodo";

const config = {
  user: "postgres",
  password: "my_pass",
  port: 5432,
  host: "localhost",
};

const createDB = async () => {
  try {
    await pgtools.createdb(config, dB);
    console.log(`database ${dB} created`);
  } catch (err) {
    console.log(err);
  }
};

createDB()
  .then(async () => {
    const pool = new Pool({
      ...config,
      database: dB,
    });

    const schemaPath = path.join(__dirname, "database.sql");
    const schema = await fs.readFile(schemaPath, "utf8");
    await pool.query(schema);
    return pool;
  })
  .then((pool) => {
    console.log("1");
    module.exports = pool;
  })
  .catch((err) => console.log(err));

database.sql只是一个简单的创建表查询。
我面临的这个问题是,module.exports甚至在pool的值成为new Pool示例化的对象之前就发生了,因此我从index.js TypeError: pool.query is not a function中得到了以下错误消息,我在代码中放置了console.logs,似乎promise链接有问题,因为2在1之前执行。
promise chain中的错误是什么?
这就是我认为的db.js的控制流,首先,调用createDB()函数,如果不存在,则创建perntodo数据库。一旦创建了数据库,则执行第一个.then()块,创建一个新的Pool并使用pool.query()将SQL模式文件加载到数据库中。Pool对象被分配给块外部声明的pool变量。
最后,执行第二个.then()块,使用module.exports将池对象设置为当前文件的导出模块。这确保池对象可用于需要此模块的应用程序的其他部分。

ctehm74n

ctehm74n1#

通常不推荐在import/require上运行异步代码,这是一个很好的例子
具体来说,index.js中的require('./db')启动对createDB的调用,并立即返回一个空的module.exports,这就是poolcreateDB开始运行之前被设置的值。
而不是让db.js在导入时立即运行以下命令:

createDB()
  .then(async () => {
   ...

你可以把它封装在一个async函数中:

async function initPool() {
  return createDB()
    .then(async () => {
       ...
       return pool;
    }
}

然后在index.js中,您可以await,直到池就绪:

const db = require("./db");
const pool = await db.initPool();

从这一点开始,它会像你期望的那样工作
旁注-也建议不要将thenawait混合使用。在幕后,它们做同样的事情,所以如果所有内容都是await,阅读起来会更容易:

async function initPool() {
  await createDB();
  ...
  return pool;
}

相关问题