我正在基于节点快速的Web应用程序中使用 Mongoose ODM 来处理 MongoDB ,该应用程序以回调方式提供其API。这种方式创建了一个回调地狱来填充文档。
编辑1:我添加了当前的工作代码。
User.remove({}, (err) => {
if (err) return console.error(err)
let admin = new User({
email: 'admin@dap.com',
password: 'dapdap'
})
admin.save((err, admin) => {
if (err) return console.error(err)
console.info('Success')
mongoose.disconnect()
})
})
是否有一种优雅的方法可以将回调转换为javascript中的async / await方式?在猫鼬环境中?
答案 0 :(得分:0)
你能配置mongoose来使用蓝鸟吗?
mongoose.Promise = require('bluebird');
然后你可以想象并做:
User.remove().then(() => {
let admin = new User({ ... });
admin.save().then((admin) => {
}).catch((err) => {
//Saving admin error handling
});
}).catch((err) {
//User remove error handling
});
答案 1 :(得分:0)
您在上面写的相同代码可以写成承诺。来自原始文档,
" Mongoose查询不是承诺。但是,它们对yield和async / await都有.then()函数。如果您需要完全成熟的承诺,请使用.exec()函数。"
因此,您可以使用async await模式,如下所示,
async function removeUser () {
// Surround the following call with a try catch
await User.remove({});
}
编辑:
这里的一个答案是关于插入蓝鸟的承诺。虽然这是一个很好的方法,但它是可选的。您可以在不插入自己的Promise库的情况下执行相同的操作。
答案 2 :(得分:0)
你可以使用Promise:
const userRemovePromise = new Promise((resolve, reject) => {
User.remove({}, (err) => {
if (err) reject();
let admin = new User({
email: 'admin@dap.com',
password: 'dapdap'
})
admin.save((err, admin) => {
if (err) reject();
resolve();
})
});
});
userRemovePromise.then(function(){
mongoose.disconnect();
});
答案 3 :(得分:0)
由于mongoose的默认承诺库mpromise现已弃用,因此您可以插入自己的promise库以使mongoose的操作与await / async一起使用。
Mongoose查询不是承诺。但是,它们对yield和async / await都有.then()函数。如果您需要完全成熟的承诺,请使用.exec()函数。
mongoose.Promise = require('bluebird'); bluebird promise
// mongoose.Promise = global.Promise; // default js promise - 4x- time slower than bluebird
async function removeUser () {
try {
await User.remove({}).exec();
let admin = new User({
email: 'admin@dap.com',
password: 'dapdap'
})
await admin.save();
} catch (e) {
console.log(e);
}
}
答案 4 :(得分:0)
Mongoose的最新版本返回Promise以及提供常规回调样式模式。由于async
函数是Promises的合成糖,因此您可以await
调用Mongoose方法。
async function clearUsers () {
try {
await User.remove({})
let admin = new User({
email: 'admin@dap.com',
password: 'dapdap'
})
await admin.save()
console.info('Success')
mongoose.disconnect()
} catch (e) {
console.error(e)
}
}
要记住的一些事情:
async
函数始终返回Promise。如果你没有从async
函数返回任何内容,它仍将返回一个Promise,它在该函数执行完成时解析,但不会以任何值解析。try/catch
函数中的async
与常规同步代码的工作方式相同。如果在try
正文throw
中任何函数调用或返回拒绝的承诺,则执行会在该行停止并继续执行{{ 1}} body。这是一种应该避免的反模式,除非你绝对需要处理特定函数中的错误,可能是为了从不同的来源提供返回值:
catch
上面的内容可能会像下面这样实现,但仍会捕获错误,不会导致运行时出现混乱/崩溃:
async function fn1 () {
throw new Error("Something went wrong")
}
async function fn2 () {
try {
await fn1()
} catch (e) {
throw e
}
}
async function fn3 () {
try {
await fn2()
} catch (e) {
throw e
}
}
async function run () {
try {
await fn3()
} catch (e) {
console.error(e)
}
}
有多种方式来编写上述代码,这些代码都是有效的,所以我建议您探索这些代码。
记住上面的例子,你的函数async function fn1 () {
throw new Error("Something went wrong")
}
function fn2 () {
return fn1()
}
function fn3 () {
return fn2()
}
async function run () {
try {
await fn3()
} catch (e) {
console.error(e)
}
}
可以改写为:
clearUsers()
然后可能以两种不同的方式呼叫;
通过直接与Promise交互:
async function clearUsers () {
await User.remove({})
let admin = new User({
email: 'admin@dap.com',
password: 'dapdap'
})
await admin.save()
mongoose.disconnect()
}
或来自另一个异步函数:
clearUsers()
.then(() => {
console.log('Success')
})
.catch((e) => {
console.error(e)
})
如果(async function () {
try {
await clearUsers()
console.log('Success')
} catch (e) {
console.error(e)
}
})()
函数中的任何函数调用,例如clearUsers()
,执行将在该行停止并返回被拒绝的承诺这将在两个变体中的相应await admin.save()
块中捕获。
答案 5 :(得分:-2)
使用Bluebird是处理promises中回调的一个很好的选择,它使得在某种程度上更容易理解。
但我会建议你试试
它专门用于管理javascript的异步特性。
图书馆的{p> This particular function会完全按照您的意愿行事。