В следующем коде MongoClient уже закрыт, когда выполняется функция обратного вызова collection.insert(). Так что жду, что collection.insert() не сработает и выдаст ошибку.
Но работает, collection.insert() нормально работает даже когда MongoClient уже закрыт.
Как это возможно?
Мой код:
const MongoClient = require('mongodb').MongoClient,
connectionUrl = 'mongodb://localhost:27017';
myDatabase = 'library',
myCollection = 'books';
MongoClient.connect(connectionUrl, function(Connectionerror, client) {
if (Connectionerror) {
throw Connectionerror;
}
console.info("Successfully connected to server");
var database = client.db(myDatabase),
collection = database.collection(myCollection);
var book = {Author:"Mark Twain",Title:"Tom Sawyer"};
collection.insert(book,function(InsertionError,result){
if (!InsertionError) {
console.info("Success : "+result.ops.length+" book(s) inserted!");
} else console.info("An insertion error was encountered!");
});
client.close();
console.info();
console.info("Mongo Client is closed");
console.info();
});
Исполнение :
$ node app-test.js
Successfully connected to server
Mongo Client is closed
Success : 1 book(s) inserted!
Книга была вставлена ПОСЛЕ закрытия клиента. Как это возможно ?
Теперь, с другой стороны, если есть два уровня обратных вызовов (collection.insert() под collection.findOne()), тогда возникает ошибка, как я и ожидал (MongoError : server instance pool was destroyed):
const MongoClient = require('mongodb').MongoClient,
connectionUrl = 'mongodb://localhost:27017';
myDatabase = 'library',
myCollection = 'books';
MongoClient.connect(connectionUrl, function(Connectionerror, client) {
if (Connectionerror) {
throw Connectionerror;
}
console.info("Successfully connected to server");
var database = client.db(myDatabase),
collection = database.collection(myCollection);
var book = {Author:"Mark Twain",Title:"Tom Sawyer"};
collection.findOne(book,function(QueryError,bookToFind){
if (!QueryError) {
if (bookToFind != null) {
console.info("This book already exists !");
} else {
collection.insert(book,function(InsertionError,result){
if (!InsertionError) {
console.info("Success : "+result.ops.length+" books inserted!");
} else {
console.info("An insertion error was encountered!");
console.info(InsertionError.stack);
}
});
}
} else console.info("A request errror was encountered !");
});
client.close();
console.info();
console.info("Mongo Client is closed");
console.info();
});
Исполнение :
$ node app-test2.js
Successfully connected to server
Mongo Client is closed
An insertion error was encountered!
MongoError: server instance pool was destroyed
(...)
Спасибо, Энтони. Я полагал, что функция обратного вызова collection.insert() будет выполнена ПОСЛЕ вызова close. В любом случае, я обновил свой вопрос дополнительным примером, вызовом collection.insert() под вызовом collection.findOne(). На этот раз я получил MongoError: server instance pool was destroyed, чего я и ожидал. Итак, почему первый случай работает, а второй нет?
Опять же, потому что вы сначала вызываете вставку перед закрытием. Во втором случае клиент получает findOne, затем закрывает, затем вставляет. Вызов findOne не включает вызов вставки - вызов вставки выполняется только после завершения findOne. Эти методы не синхронны (отсюда и обратные вызовы!), Поэтому вставка добавляется в список задач цикла событий, но также в этом списке задач - и перед вставкой - есть вызов закрытия.
Хорошо, спасибо всем, теперь я понял. Я неправильно понял использование функций обратного вызова (это мой первый шаг с Javascript / Node.js). Теперь я понимаю: в первом примере вызывается вставка, затем клиент закрывается, а затем вызывается обратный вызов вставки. То же самое во втором примере: вызывается findOne, клиент закрывается и вызывается функция обратного вызова findOne, которая включает вставку, которая завершается ошибкой из-за закрытия клиента.





Второй пример работает так же, как и первый. 1. Выполняется поисковый запрос. 2. Пока не поступит ответ от базы данных, будет выполняться client.close (). 3. Теперь, когда ответ получен на первый запрос, второй запрос выдаст исключение / ошибку, потому что шаг 2 закрыл соединение.
Фактически, ваш console.info отвечает на ваш собственный вопрос.
Поскольку ваш запрос на вставку находится перед вызовом закрытия, поэтому данные вставляются ... Это не зависит от обратного вызова ...