【发布时间】:2020-04-22 22:55:28
【问题描述】:
我正在尝试重写我编写的用于为 MongoDB 数据库提供种子的模块。它最初可以很好地处理回调,但我想转向 Promises。但是,执行和结果似乎没有任何意义。
Seeder 对象中有三个通用函数:
// functions will be renamed
Seeder.prototype.connectPromise = function (url, opts) {
return new Promise((resolve,reject) => {
try {
mongoose.connect(url, opts).then(() => {
const connected = mongoose.connection.readyState == 1
this.connected = connected
resolve(connected)
})
} catch (error) {
reject(error)
}
})
}
[...]
Seeder.prototype.seedDataPromise = function (data) {
return new Promise((resolve,reject) => {
if (!this.connected) reject(new Error('Not connected to MongoDB'))
// Stores all promises to be resolved
var promises = []
// Fetch the model via its name string from mongoose
const Model = mongoose.model(data.model)
// For each object in the 'documents' field of the main object
data.documents.forEach((item) => {
// generates a Promise for a single item insertion.
promises.push(promise(Model, item))
})
// Fulfil each Promise in parallel
Promise.all(promises).then(resolve(true)).catch((e)=>{
reject(e)
})
})
}
[...]
Seeder.prototype.disconnect = function () {
mongoose.disconnect()
this.connected = false
this.listeners.forEach((l) => {
if (l.cause == 'onDisconnect') l.effect()
})
}
代码的主要逻辑没有问题。我可以让它正确地播种数据。然而,当使用 Promises 时,数据库在其他任何事情完成之前就断开连接,尽管断开连接函数被称为 .finally()。
我正在像这样运行这些函数:
Seeder.addListener('onConnect', function onConnect () { console.log('Connected') })
Seeder.addListener('onDisconnect', function onDisconnect () {console.log('Disconnected')})
Seeder.connectPromise(mongoURI, options).then(
Seeder.seedDataPromise(data)
).catch((error) => { <-- I am catching the error, why is it saying its unhandled?
console.error(error)
}).finally(Seeder.disconnect())
输出是这样的:
Disconnected
(node:14688) UnhandledPromiseRejectionWarning: Error: Not connected to MongoDB
at Promise (C:\Users\johnn\Documents\Code\node projects\mongoose-seeder\seed.js:83:37)
坦率地说,这对我来说没有意义,正如我在调用reject() 的堆栈跟踪中指出的那样。并且处理了这个拒绝,因为我有一个如上所示的 catch 语句。此外,我不明白为什么数据库甚至没有机会连接,因为 finally() 块应该最后调用。
除了其他建议外,解决方案是返回Promise.all 调用。
【问题讨论】:
-
你的
connectPromise()函数是一个 Promise 反模式。没有理由将现有的 Promise 包装在手动创建的 Promise 包装器中。这被认为是一种承诺反模式。只需执行return mongoose.connect().then();。这会很好地回报你的承诺。 -
请不要为您的问题添加解决方案。 Stack Overflow 的格式是问题出现在问题部分,答案出现在答案部分。
-
没有。对于任何搜索的人来说,立即看到答案更有用。
-
没有。这不是 Stack Overflow 的工作方式 (ref)。我已恢复您的更改。