Вы, кажется, упускаете понятие.Во-первых, как уже говорилось, все операции mongoose возвращают Promise или, по крайней мере, объект типа «Promise like», который можно сразу разрешить с помощью then()
вместо передачи функции обратного вызова.Это может быть представлено двумя способами.
Либо с синтаксисом async/await
и блоком try..catch
:
const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost/test';
mongoose.set('debug', true);
mongoose.Promise = global.Promise;
const characterSchema = new Schema({
name: String
});
const Character = mongoose.model('Character', characterSchema);
const log = data => console.log(JSON.stringify(data,undefined,2));
const doCount = async () => {
let count = await Character.count();
if (count > 3)
throw new Error("too many charaters");
return count;
};
(async function() {
try {
const conn = await mongoose.connect(uri);
await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()))
await Character.insertMany(
["Huey","Duey","Louie"].map(name => ({ name }))
);
let count = await doCount();
log({ count });
await Character.create({ name: 'Donald' });
let newCount = await doCount();
console.log("never get here");
} catch(e) {
console.error(e)
} finally {
mongoose.disconnect();
}
})()
Или со стандартным синтаксисом then()
и catch()
:
const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost/test';
mongoose.set('debug', true);
mongoose.Promise = global.Promise;
const characterSchema = new Schema({
name: String
});
const Character = mongoose.model('Character', characterSchema);
const log = data => console.log(JSON.stringify(data,undefined,2));
function doCount() {
return Character.count()
.then(count => {
if (count > 3)
throw new Error("too many charaters");
return count;
});
};
(function() {
mongoose.connect(uri)
.then(conn => Promise.all(
Object.entries(conn.models).map(([k,m]) => m.remove())
))
.then(() => Character.insertMany(
["Huey","Duey","Louie"].map(name => ({ name }))
))
.then(() => doCount())
.then(count => log({ count }))
.then(() => Character.create({ name: 'Donald' }))
.then(() => doCount())
.then(() => console.log("never get here"))
.catch(e => console.error(e))
.then(() => mongoose.disconnect() );
})()
И вывод обоих списков одинаков:
Mongoose: characters.remove({}, {})
Mongoose: characters.insertMany([ { _id: 5b0f66ec5580010efc5d0602, name: 'Huey', __v: 0 }, { _id: 5b0f66ec5580010efc5d0603, name: 'Duey', __v: 0 }, { _id: 5b0f66ec5580010efc5d0604, name: 'Louie', __v: 0 } ], {})
Mongoose: characters.count({}, {})
{
"count": 3
}
Mongoose: characters.insertOne({ _id: ObjectId("5b0f66ec5580010efc5d0605"), name: 'Donald', __v: 0 })
Mongoose: characters.count({}, {})
Error: too many charaters
at doCount (/home/projects/characters/index.js:20:11)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
Как вы можете видеть, функция с радостью возвращает свое значение, где count
остается 3 или ниже, но затем выдаетисключение, которое останавливает дальнейшее выполнение, когда count
будет больше 3, поскольку сообщение "never get here"
никогда не регистрируется.
Таким образом, здесь нет необходимости в «обратных вызовах», и вы не будете использовать его, если только выОбернутый в Обещание может все равно выполнить тот же тип обработки ошибок.
Но если у вас есть "ошибка", то throw
ошибка.Это прекрасно работает в цепочке обещаний, но «обратный вызов», который не возвращается как обещание, просто не является частью этой цепочки и никогда не может быть «пойман».Так что просто не используйте обратный вызов, когда вам это не нужно.
Только для ударов, завершение обратного вызова с обещанием будет сделано как:
function doCount() {
return new Promise((resolve,reject) =>
Character.count().exec((err,count) => {
if (count > 3)
reject(new Error("too many charaters"));
resolve(count);
})
);
};
Но это не отмеченонеобходимо, учитывая, что нативные методы возвращают что-то, что вы в любом случае можете разрешить как Обещание.