Экспорт модуля Node.js Async / Await

Я как бы новичок в создании модулей и задавался вопросом о module.exports и ждал, пока асинхронные функции (например, функция mongo connect) завершатся и экспортируют результат. Переменные правильно определяются с помощью async / await в модуле, но при попытке зарегистрировать их, запрашивая модуль, они отображаются как undefined. Если бы кто-то мог указать мне правильное направление, было бы здорово. Вот код, который у меня есть:

// 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.info(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.info it from there
    module.exports = {
      client,
      db
    }
  }
})(module)

А вот js, для которого требуется модуль

// test.js

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

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

Я довольно хорошо знаком с js и все еще активно изучаю и изучаю такие вещи, как async / await и подобные функции, но да ... я действительно не могу понять это

Я использовал некоторые примеры кода из официального драйвера узла mongodb, чтобы проверить это. Но мне было бы полезно знать это в целом. Пример кода можно найти здесь

brocococonut 02.07.2018 21:20
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
10
1
23 108
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы должны экспортировать синхронно, поэтому напрямую экспортировать client и db невозможно. Однако вы можете экспортировать обещание, которое разрешается в client и db:

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) не является подходящим обработчиком ошибок, если вы не можете справиться с ошибкой, просто сбой

Ах, понятно ... В конце концов, я буду экспортировать то, для чего требуется соединение mongo, а не само соединение. Хотя в этом есть смысл, спасибо :)

brocococonut 02.07.2018 21:30

@brocococonut рад помочь :)

Jonas Wilms 02.07.2018 21:32

Поскольку вы возвращаете функцию, этот подход откроет новое соединение для каждого требования. не так ли?

Elad 02.12.2019 15:29

@elad нет, я возвращаю возвращаемое значение функции

Jonas Wilms 02.12.2019 16:03

Спасибо. Так что мне нужно требовать этого в каждой функции, которую я хочу запросить в БД? чувствовать себя очень "шаблонным"

Elad 02.12.2019 16:10

@elad в каждом файле (/ module)

Jonas Wilms 02.12.2019 16:15

Как мы можем добиться того же для импорта es6 (import abc from 'sample-module')?

Dev AKS 03.12.2020 17:49

@DevAKS const abc = await import("./sample-module");

Jonas Wilms 03.12.2020 18:12

решение, предоставленное выше @Jonas Wilms, работает, но требует вызова асинхронной функции каждый раз, когда мы хотим повторно использовать соединение. альтернативный способ - использовать функцию обратного вызова для возврата клиентского объекта 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}

тогда мы можем использовать метод mongoClient в другом файле (экспресс-маршрут или любой другой файл js).

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.info(err);
    return res.status(500).json({ error: err});
  }

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

Это создаст несколько клиентов ... не уверен, что это необходимо. Также конечная точка API ответит ошибкой, если вы вызовете ее до загрузки клиента db.

Jonas Wilms 06.03.2020 19:44

Другие вопросы по теме