MongoDB
Node.js и MongoDB: как правильно закрывать client.close
В Node.js client.close() нужно вызывать тогда, когда приложение действительно завершает работу с MongoDB. В одноразовом скрипте закрывайте клиент в finally. В Express-сервере не закрывайте подключение после каждого HTTP-запроса: создайте клиент один раз при старте и закрывайте его при остановке процесса
Пример для скрипта:
import { MongoClient } from "mongodb";
const client = new MongoClient("mongodb://localhost:27017");
try {
await client.connect();
const db = client.db("shop");
const products = await db.collection("products").find().toArray();
console.log(products);
} finally {
await client.close();
}
Так соединение закроется даже при ошибке
Express-приложение
Для сервера лучше подключиться один раз:
import express from "express";
import { MongoClient } from "mongodb";
const app = express();
const client = new MongoClient(process.env.MONGODB_URI);
await client.connect();
const db = client.db("shop");
app.get("/products", async (req, res) => {
const products = await db.collection("products").find().toArray();
res.json(products);
});
const server = app.listen(3000);
Не делайте так внутри каждого route:
await client.connect();
await client.close();
Это создает лишнюю нагрузку и может замедлить приложение
Graceful shutdown
Закройте MongoDB-клиент при остановке сервера:
async function shutdown() {
server.close(async () => {
await client.close();
process.exit(0);
});
}
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
Так приложение перестает принимать новые запросы, останавливает сервер и затем завершает MongoDB-клиент
Когда close точно нужен
client.close() нужен в CLI-скриптах, миграциях, seed-скриптах, тестах и обработчиках завершения процесса. Если код запускается, делает работу и заканчивает выполнение, закрытие обязательно. Иначе Node.js может продолжать висеть из-за открытого подключения
Как понять, что клиент закрывают слишком рано
Типичный симптом — первый запрос работает, а второй падает или снова долго подключается к базе. В логах может быть видно, что приложение создает новый MongoClient при каждом обращении к API. Для Express это сигнал пересмотреть архитектуру: подключение должно жить на уровне приложения, а route должен только брать готовую коллекцию и выполнять запрос
Нормальная схема такая: connect при старте, работа routes, close при остановке процесса. Это проще отлаживать и легче масштабировать
Когда close мешает
Если закрыть клиент после первого запроса Express, следующий route может получить ошибку вроде MongoClient must be connected или начнет заново открывать соединение. Для веб-приложения это неправильный жизненный цикл
Частые ошибки
Закрывают клиент после каждого запроса
Создайте подключение один раз и переиспользуйте db
Не используют finally в скрипте
При ошибке соединение может остаться открытым. В скриптах закрывайте в finally
Не ждут await client.close()
close() асинхронный. Используйте await, чтобы завершение прошло корректно
Создают много MongoClient
Один процесс обычно должен иметь один общий клиент для приложения
Не обрабатывают остановку процесса
Если приложение работает на сервере, добавьте обработчики SIGTERM и SIGINT. Так деплой или остановка контейнера пройдут аккуратнее
Что почитать дальше по MongoDB
Если нужен общий маршрут по теме, откройте рубрику MongoDB. Для соседних задач пригодятся эти разборы:
- Node.js + MongoDB: мини-проект с заявками
- Как правильно заполнить MongoDB через Mongoose
- Как правильно составить запрос в MongoDB
- Discord bot на Python и MongoDB: как задать проверку