Dzieje się tak, ponieważ kod zawiera antywzorzec:za każdym razem, gdy przychodzi nowe żądanie, otwiera nowe połączenie z bazą danych, a następnie zamyka je po wysłaniu odpowiedzi. Następnie próbował ponownie użyć zamkniętego połączenia, stąd komunikat o błędzie, który widzisz przy drugim żądaniu.
Chcesz połączyć się tylko raz z bazą danych przez cały okres istnienia aplikacji przy użyciu globalnego obiektu połączenia, a następnie użyć tego globalnego obiektu do wykonania operacji na bazie danych.
Użycie tego globalnego obiektu umożliwia sterownikowi MongoDB prawidłowe utworzenie puli połączeń z bazą danych. Ta pula jest zarządzana przez sterownik MongoDB i pozwala uniknąć kosztownego wzorca łączenia/ponownego łączenia.
Na przykład:
// listen on this port
const port = 3000
// global database client object
var client = null
// listen on the configured port once database connection is established
MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true }, (err, res) => {
assert.equal(null, err)
client = res
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
})
// use the client global object for database operations
app.get('/', (req, res) => {
db = req.query.db
col = req.query.col
client.db(db).collection(col).find({}).toArray((err, docs) => {
assert.equal(null, err)
res.send(JSON.stringify(docs))
})
})
Edytuj aby odpowiedzieć na twoje pytanie w komentarzu:
Dzieje się tak, ponieważ w oryginalnym kodzie dbClient
został zdefiniowany globalnie. Kiedy dbClient.close()
został wywołany, globalny dbClient
był zamknięty. Wystąpił błąd, gdy ten dbClient
obiekt został ponownie wykorzystany. Dzieje się tak, ponieważ connect()
tworzy pulę połączeń zamiast pojedynczego połączenia i nie spodziewano się, że będzie wywoływana wiele razy na wywołanie.
Jeśli przeniesiesz dbClient
zmienna z zakresu globalnego do app.get()
kontekst, przekonasz się, że nie zostanie wygenerowany żaden błąd, gdy wielokrotnie wywołasz punkt końcowy HTTP, jako nowy dbClient
obiekt był tworzony za każdym razem.
To powiedziawszy, chociaż zadziała, nie jest to zalecany wzorzec. Lepiej jest użyć wzorca podobnego do przykładowego kodu, który zamieściłem powyżej.