Node.js的Async/Await模块导出

17

我对模块创建还比较陌生,想了解一下module.exports和等待异步函数(例如mongo连接函数)完成并导出结果的相关知识。在模块中使用async/await变量可以得到正确定义,但是在尝试通过require模块记录它们时,它们会显示为未定义。如果有人能指点我正确的方向,那就太好了。以下是我目前的代码:

// module.js

const MongoClient = require('mongodb').MongoClient
const mongo_host = '127.0.0.1'
const mongo_db = 'test'
const mongo_port = '27017';

(async module => {

  var client, db
  var url = `mongodb://${mongo_host}:${mongo_port}/${mongo_db}`

  try {
    // Use connect method to connect to the Server
    client = await MongoClient.connect(url, {
      useNewUrlParser: true
    })

    db = client.db(mongo_db)
  } catch (err) {
    console.error(err)
  } finally {
    // Exporting mongo just to test things
    console.log(client) // Just to test things I tried logging the client here and it works. It doesn't show 'undefined' like test.js does when trying to console.log it from there
    module.exports = {
      client,
      db
    }
  }
})(module)

以下是需要引入该模块的JavaScript代码

// test.js

const {client} = require('./module')

console.log(client) // Logs 'undefined'

我对js比较熟悉,目前还在积极学习和探索像async/await等功能,但是...我真的弄不清楚那个问题


我已经使用了mongodb官方node驱动程序中的一些示例代码来进行测试。但是这对我来说通常也会有用处。 示例代码可以在此处找到:http://mongodb.github.io/node-mongodb-native/3.1/reference/ecmascriptnext/connecting/ - brocococonut
2个回答

29

您必须同步导出,因此无法直接导出clientdb。但是,您可以导出一个解析为clientdb的Promise:

module.exports = (async function() {
 const client = await MongoClient.connect(url, {
   useNewUrlParser: true
 });

  const db = client.db(mongo_db);
  return { client, db };
})();

那么您可以这样导入它:

const {client, db} = await require("yourmodule");

(它必须是在一个异步函数中)

PS:console.error(err)不是一个适当的错误处理程序,如果你无法处理错误,那就崩溃吧。


因为你返回了一个函数,所以这种方法会为每个 require 打开一个新的连接,对吧? - Elad
@elad 不,我返回一个函数的返回值 - Jonas Wilms
1
谢谢。那么我需要在每个想要查询数据库的函数中都要求它吗?感觉很“样板式”。 - Elad
在每个文件(/模块)中都要加上@elad。 - Jonas Wilms
1
const abc = await import("./sample-module"); - Jonas Wilms
显示剩余3条评论

-1

@Jonas Wilms提供的解决方案是可行的,但每次想要重用连接时都需要在异步函数中调用requires。另一种替代方法是使用回调函数来返回mongoDB客户端对象。

mongo.js:

const MongoClient = require('mongodb').MongoClient;

const uri = "mongodb+srv://<user>:<pwd>@<host and port>?retryWrites=true";

const mongoClient = async function(cb) {
    const client = await MongoClient.connect(uri, {
             useNewUrlParser: true
         });
         cb(client);
};

module.exports = {mongoClient}

然后我们可以在不同的文件(express路由或任何其他js文件)中使用mongoClient方法。

app.js:

var client;
const mongo = require('path to mongo.js');
mongo.mongoClient((connection) => {
  client = connection;
});
//declare express app and listen....

//simple post reuest to store a student..
app.post('/', async (req, res, next) => {
  const newStudent = {
    name: req.body.name,
    description: req.body.description,
    studentId: req.body.studetId,
    image: req.body.image
  };
  try
  {

    await client.db('university').collection('students').insertOne({newStudent});
  }
  catch(err)
  {
    console.log(err);
    return res.status(500).json({ error: err});
  }

  return res.status(201).json({ message: 'Student added'});
};

这将创建多个客户端...不确定是否需要。此外,如果在加载数据库客户端之前调用API端点,则会响应错误。 - Jonas Wilms

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接