Зачем смешивать async/await
со стандартным синтаксисом Promise, когда вы можете просто написать все это одним стандартным способом. Кроме того, все методы mongoose возвращают Promise
в любом случае, поэтому я не понимаю, почему вы даже пытаетесь обернуть обратный вызов Promise
.
Листинг в основном показывает неправильное понимание Обещаний и async/await
, поэтому приведенный здесь пример должен прояснить некоторые вещи:
// Require mongoose and add your model definitions
const uri = 'mongodb://localhost:27017/test';
const opts = { useNewUrlParser: true };
(async function() {
try {
const conn = await mongoose.connect(uri, opts);
// get your 'data' from somewhere of course.
for ( let wip of data ) {
let existingWIP = await WIP.findOne(query_goes_here);
if (existingWip) { // Asking for "id" on null would be an error
// Update existing record
console.log(`Existing WIP: ${existingWip.id}`);
... assign some values ...
existingWip.lastModified = moment.now();
let updatedWip = await existingWip.save()
console.log(`Updated WIP ${updatedWip.id}`); // though you should understand this does not change
// as id is immutable
} else {
let newWip = await WIP.create(wip); // not sure why you are creating a function
// but all mongoose methods return a promise anyway
// maybe do something
}
}
} catch (e) {
console.error(e);
} finally {
mongoose.disconnect();
}
})()
Отмечая, что await
в основном означает, что вам не нужно делать then()
, потому что на самом деле это одно и то же, но только с более чистым синтаксисом . То же самое относится к .catch()
, так как вместо этого он становится намного чище try..catch
.
Если нужно, разбейте это функционально, но если вы просто делаете быстрый скрипт для загрузки и обновления некоторых вещей, то, вероятно, в этом нет особого смысла. Просто убедитесь, что все реализации function()
возвращают Promise
(то есть результат метода mongoose) и что вы await
их.
Кроме того, вы можете в основном взглянуть на findOneAndUpdate()
и, в частности, на опцию "upsert". Одно это в основном удалит ваше условие if..then..else
и сделает все это в одном запросе вместо разделенных find()
и save()
// Require mongoose and add your model definitions
const uri = 'mongodb://localhost:27017/test';
const opts = { useNewUrlParser: true };
(async function() {
try {
const conn = await mongoose.connect(uri, opts);
// get your 'data' from somewhere of course.
for ( let wip of data ) {
let updatedWip = await WIP.findOneAndUpdate(
query_goes_here,
update_statement_goes_here,
{ upsert: true, new: true } // need these options
);
console.log(`Updated WIP ${updatedWip.id}`);
}
} catch (e) {
console.error(e);
} finally {
mongoose.disconnect();
}
})()
Или, конечно, если вам просто не нужно ничего делать в «цикле», тогда вы можете просто использовать bulkWrite()
:
// Require mongoose and add your model definitions
const uri = 'mongodb://localhost:27017/test';
const opts = { useNewUrlParser: true };
(async function() {
try {
const conn = await mongoose.connect(uri, opts);
// get your 'data' from somewhere of course.
let result = await WIP.bulkWrite(
data.map(wip =>
({
updateOne: {
filter: query_based_on_wip_values
update: update_based_on_wip_values,
upsert: true
}
})
)
);
} catch (e) {
console.error(e);
} finally {
mongoose.disconnect();
}
})()
И это, конечно, требует только один запрос к серверу с один ответ для всего содержимого в массиве. Если массив особенно велик, вы можете разбить его на части. Но опять же, для «большого массива» вы должны загружать данные по частям, чтобы не все они были в массиве.
В целом, выберите один структурный шаблон и придерживайтесь его, и найдите время, чтобы понять методы API и то, что они делают. Обычно find()
затем изменяют в коде, а шаблон save()
- это очень плохая практика , и в основном вводит дополнительные накладные расходы на запросы назад и вперед, плюс очевидная проблема, заключающаяся в том, что прочитанные вами данные, возможно, изменились другим процессом / обновить к тому времени, когда вы решите написать его обратно.