Почему функция обратного вызова все еще может вставляться в mongoDB, даже когда клиент закрыт?

В следующем коде 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
(...)

Поскольку ваш запрос на вставку находится перед вызовом закрытия, поэтому данные вставляются ... Это не зависит от обратного вызова ...

Ashh 30.06.2018 19:14

Спасибо, Энтони. Я полагал, что функция обратного вызова collection.insert() будет выполнена ПОСЛЕ вызова close. В любом случае, я обновил свой вопрос дополнительным примером, вызовом collection.insert() под вызовом collection.findOne(). На этот раз я получил MongoError: server instance pool was destroyed, чего я и ожидал. Итак, почему первый случай работает, а второй нет?

ChennyStar 30.06.2018 19:33

Опять же, потому что вы сначала вызываете вставку перед закрытием. Во втором случае клиент получает findOne, затем закрывает, затем вставляет. Вызов findOne не включает вызов вставки - вызов вставки выполняется только после завершения findOne. Эти методы не синхронны (отсюда и обратные вызовы!), Поэтому вставка добавляется в список задач цикла событий, но также в этом списке задач - и перед вставкой - есть вызов закрытия.

tehhowch 30.06.2018 19:40

Хорошо, спасибо всем, теперь я понял. Я неправильно понял использование функций обратного вызова (это мой первый шаг с Javascript / Node.js). Теперь я понимаю: в первом примере вызывается вставка, затем клиент закрывается, а затем вызывается обратный вызов вставки. То же самое во втором примере: вызывается findOne, клиент закрывается и вызывается функция обратного вызова findOne, которая включает вставку, которая завершается ошибкой из-за закрытия клиента.

ChennyStar 30.06.2018 20:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
93
1

Ответы 1

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

Фактически, ваш console.info отвечает на ваш собственный вопрос.

Другие вопросы по теме