NextJS продолжает создавать новое соединение с MongoDB при использовании pages API

#next.js

#next.js

Вопрос:

Я следовал этому примеру на официальной странице NextJS на Github, и мне удалось запустить свой проект.

Ниже приведена моя файловая структура:

 📦pages
 ┣ 📂api
 ┃ ┣ 📂auth
 ┃ ┃ ┣ 📜load.ts
 ┃ ┃ ┣ 📜login.ts
 ┃ ┃ ┗ 📜register.ts
 ┃ ┣ 📂contact
 ┃ ┃ ┗ 📜index.ts
 ┃ ┣ 📂listings
 ┃ ┃ ┣ 📜paginate.ts
 ┃ ┃ ┣ 📜index.ts
 ┣ 📜_app.tsx
 ┣ 📜_document.tsx
 ┣ 📜_error.tsx
 ┗ 📜index.tsx
  

Большинство из этих маршрутов api выполняются await connectDb() перед продолжением. Вот оно:

 import mongoose from 'mongoose';
import config from 'config';

const connectionObject: any = {};

const connectDb = async () => {
    if (connectionObject.isConnected) {
        return;
    }

    try {
        const db = await mongoose.connect(process.env.MONGODB_URI || config.get('mongoURI'), {
            useNewUrlParser: true,
            useUnifiedTopology: true,
            useFindAndModify: false,
            useCreateIndex: true,
        });

        connectionObject.isConnected = db.connections[0].readyState;
    } catch (err) {
        console.log('Failed to connect to db', err);
    }
};

export default connectDb;
  

Однако проблема, с которой я сталкиваюсь прямо сейчас, заключается в том, что connectionObject по какой-то причине, похоже, освобождается, когда используются разные маршруты.

Я не могу быть уверен, но я думаю, что до тех пор, пока маршрут, который был выбран, находится в том же каталоге, что и предыдущий маршрут, который был выбран до него, тогда соединение не будет восстановлено. Итак, если я нажимаю login.ts после нажатия paginate.ts , будет создано новое соединение с MongoDB. Аналогично, если я нажму load.ts после login.ts , новое соединение НЕ будет создано.

Я чувствую, что мне не хватает чего-то элементарного здесь. Какие у меня варианты / что я делаю не так?

Я обнаружил аналогичную проблему с Github, которая, похоже, имеет отношение к моей проблеме, но мне это не помогло.

Обсуждение на Github

Комментарии:

1. попробуйте использовать пул соединений? редактировать: неважно, я вижу, что вы ищете сейчас

Ответ №1:

Каждый маршрут API является лямбдой, поэтому каждый из них имеет свое собственное состояние

Комментарии:

1. Я изменил connectDb функцию на обычную, но это ничего не исправило. Кажется, что каждый маршрут по-прежнему имеет свое собственное состояние

2. @MikeK это не то, что я имею в виду. Вы можете представить каждый маршрут API (файл) как сервер. таким образом, наличие двух маршрутов API похоже на запуск двух серверов, каждый из которых имеет свое собственное глобальное состояние

3. Я понимаю, но возможно ли это как-то исправить? Я использовал пользовательский сервер вместо их pages API, но мне не удалось развернуть его в Vercel таким образом. Развертывание в Vercel поддерживается, только если я использую их встроенный pages API, но недостатком здесь является то, что каждый файл имеет свое собственное состояние, как вы говорите. Итак, какие у меня есть варианты здесь?

4. @MikeK лучше всего использовать другую платформу, такую как Heroku. Но если вы все еще хотите использовать Vercel, вы можете создать специальный маршрут API, который будет содержать ваши состояния, и вы можете отправлять к нему запросы с других маршрутов, чтобы получить эти состояния или обновить их

Ответ №2:

TLDR; consts имеют область действия блока.(connectionObject)

Согласно документации Mozilla const, константы ограничены областью блоков, так же как переменные, определенные с помощью ключевого слова let . Значение константы не может быть изменено путем переназначения, и его нельзя повторно объявить

Итак, в вашем случае connectionObject остается пустым, потому что это область изменения, в которой вы обновляете этот блок. Следовательно, за пределами блока он пуст.

Лучший пример для проверки — первый фрагмент кода в приведенной выше документации

 const number = 42;

try {
  number = 99;
} catch (err) {
  console.log(err);
  // expected output: TypeError: invalid assignment to const `number'
  // Note - error messages will vary depending on browser
}

console.log(number);
// expected output: 42