Честно говоря, вам не только «везет» с действиями, которые необходимо решить перед вызовом client.close()
, но также может быть «потенциальная» проблема с двумя операторами, работающими параллельно.
В идеале вы должны вместо этого использовать bulkWrite()
и сделать «одиночный» запрос с обоими действиями, содержащимися в нем.«Один запрос» также имеет «один ответ», поэтому нет проблем с ожиданием разрешения нескольких обещаний:
collection.bulkWrite(
[
...listOfInsertDocuments.map(document => ({ "insertOne": { document } })),
{ "deleteMany": { "filter": filterCondition } }
]
)
.then(() => console.log("will close"))
.catch(e => console.error(e))
.then(() => client.close());
Действие по умолчанию bulkWrite()
состоит в том, что операции выполняются "упорядочено "и выполняется последовательно в том же порядке, в котором они были представлены в массиве" представленных действий ".Array.map()
, используемый здесь для создания действий insertOne
, на самом деле является именно тем, что метод insertMany()
фактически делает в реализации базового драйвера.
ВФакт ВСЕ, что такие методы драйвера фактически называют базовые методы «Bulk API» как современный способ работы.bulkWrite()
явно абстрагируется от фактического «Bulk API», чтобы изящно понизить требования к «устаревшему» API при подключении к экземпляру MongoDB ранее, чем MongoDB 2.6.
Другой способ сделать это - «параллельное» выполнение, явно указав "ordered": false
:
collection.bulkWrite(
[
...listOfInsertDocuments.map(document => ({ "insertOne": { document } })),
{ "deleteMany": { "filter": filterCondition } }
],
{ "ordered": false }
)
.then(() => console.log("will close"))
.catch(e => console.error(e))
.then(() => client.close());
Это намеренно означает, что ни одно из действий не зависит от других, выполняющих «первый».Поэтому, если вы действительно «вставляете» что-то, что вы также «удаляете», то нет никакой гарантии, что это произойдет в каком-то конкретном порядке.
Помимо «параллелизма», общее назначение "ordered": false
разрешить продолжение «по ошибке».В таком случае все «пакетные» действия фактически предпринимаются, и в ответе об исключительной ситуации вы получаете подробную информацию о том, в каких «индексных позициях» в массиве предусмотренных действий произошел какой-либо сбой.
Поведение тогда"sort" выполняется в "mimicry" следующим вызовом Promise.all()
:
Promise.all([
collection.insertMany(..., { "ordered": false }).then(()=> { console.log("inserted") }),
collection.deleteMany(...).then(()=> { console.log("deleted") })
]).then(() => console.log("will close"))
.catch(e => console.error(e))
.then(() => client.close());
Это, конечно, выполняется в "параллельном режиме", но запускает "несколько запросов", что создает большийнакладные расходы при обратной и обратной связи с сервером.Цель предыдущих примеров - избежать этого и, следовательно, лучшего варианта.
А для «полноты» вы всегда можете, конечно, «связать» обещания:
collection.insertMany(...)
.then(() => console.log("inserted")),
.then(() => collection.deleteMany(...)
.then(()=> console.log("deleted"))
.then(() => console.log("will close"))
.catch(e => console.error(e))
.then(() => client.close());
Таким образом«все» выполняется последовательно, но, конечно, все они запускают отдельные запросы.
Так что, хотя есть способы обработать «ожидание» разрешения Promise, обычно лучше сделать «один вызов» и просто ждать, чтоВместо этого «массовый» ответ.