Всего есть 2 вызова функции get (), 1 перед экспортом, как вы можете видеть, и еще один из теста мокко.
Я подозреваю, что выход имеет дополнительный=> connect to database
.Как я уже говорил в комментариях: есть «условие гонки», когда get()
может быть вызвано несколько раз, прежде чем будет установлено this.cachedDb
, что приведет к созданию нескольких соединений / экземпляров Db.
Например:
const a = client.get();
const b = client.get();
// then
a.then(resultA => {
b.then(resultB => {
console.log(resultA !== resultB); // true
});
});
Решение
Проблема может быть решена путем сохранения обещания в качестве кэшированного значения (также нет необходимости указывать ключевое слово async
в методахкак указал Рэнди, поскольку в любом из методов не ожидается никаких значений, поэтому вы можете просто вернуть обещания):
import {Db, MongoClient} from "mongodb";
import {MongoConfig} from '../config/config'
class DbClient {
private cachedGet: Promise<Db> | undefined;
private connectToDatabase() {
console.log('=> connect to database');
const connectionString = `mongodb://${MongoConfig.host}:${MongoConfig.port}`;
return MongoClient.connect(connectionString);
}
get() {
if (!this.cachedGet) {
this.cachedGet = this.connectToDatabase();
// clear the cached promise on failure so that if a caller
// calls this again, it will try to reconnect
this.cachedGet.catch(() => {
this.cachedGet = undefined;
});
}
return this.cachedGet;
}
}
let client = new DbClient();
client.get();
export = client;
Примечание: я не уверен насчет лучшего способа использования MongoDB (яЯ никогда не использовал его), но я подозреваю, что соединения не должны быть такими долгоживущими, чтобы их можно было так кэшировать (или, вероятно, их следует кэшировать только на короткое время, а затем отключить).Вы должны будете исследовать это все же.