【问题标题】:Where am I supposed to catch this Promise MongoError?我应该在哪里捕获这个 Promise MongoError?
【发布时间】:2018-04-24 23:12:32
【问题描述】:

我升级了我的猫鼬,所以我当然开始得到这些:

DeprecationWarning: Mongoose: mpromise (mongoose's default promise library)
is deprecated, plug in your own promise library instead:
http://mongoosejs.com/docs/promises.html

所以我添加了mongoose.Promise = global.Promise。都好。除了......现在我得到了这个人:

(node:20760) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: exception: Index with name: stampRoundedToNearestHour_1 already exists with different options
(node:20760) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

修复潜在错误很容易,但我不知道应该在哪里捕获它,这样以后的 Node 版本就不会突然出现如果他们遇到类似的事情会崩溃。我已经生成了产生错误的代码的最小版本。这是一个 javascript 文件:

var mongoose = require('mongoose')
mongoose.Promise = global.Promise

var TestSchema = mongoose.Schema({
  num: Number,
})

TestSchema.index({'num': 1}, { sparse: true })
TestSchema.index({'num': 1}, { sparse: false })
// The above line is deliberately designed to be problematic.
// My question isn't how to not get an error,
// it's that I don't know where to catch it when I do!

// If this line is commented out, there's no error
// but it doesn't return a promise, so I can't .then or .catch on it
var Test = mongoose.model('Test', TestSchema)

mongoose.connect(process.env.MONGOLAB_URI, {useMongoClient: true})
.then(function () {
  console.log("mongoose.connected successfully")
}).catch(function (err) {
  console.log("mongoose.connect catch", err)
})

如您所见,我在 mongoose.connect() 函数上尝试了两种错误处理,但运行时输出的是

mongoose.connected successfully
(node:26795) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: exception: Index with name: num_1 already exists with different options
(node:26795) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

我已尝试将.catch(...) 添加到此处的所有其他函数中:

  • mongoose.Schema(...)
  • TestSchema.index({'num': 1}, { sparse: true })
  • mongoose.model('Test', TestSchema)
  • 甚至require('mongoose')(这感觉很愚蠢,但我试过了)

...以及我系统中的一些其他功能,我可以在保持代码损坏的同时删除这些功能。

但在所有这些情况下TypeError: WHATEVER.catch is not a function

我应该在哪里看到这个MongoError? (再一次,我知道如何防止它)

【问题讨论】:

  • 使用.then(successFunction, errorFunction) 有点忽略了.catch(),这对于.then(null,errorFunction) 来说真的只是“糖”。这是产生错误的所有代码吗?您确实“不应该”在实际连接“之后”建立模型,但这并不是真正的错误原因。所以这实际上只是我在这里看到的承诺链语法。除非可能有其他代码?
  • 简单地说。试试看:mongoose.connect(process.env.MONGOLAB_URI, {useMongoClient: true}).then( () => console.log('connected') ).catch( err => console.error(err ) );,因为你的现有代码中似乎有未声明的变量应该抛出“未捕获的异常”
  • @NeilLunn 是的,我知道。我很茫然,因为这实际上是所有代码,所以我把.catch() 卡在TypeError 允许我的任何地方。这实际上是一个 js 文件,如果你运行它就会产生这个错误。
  • “只是尝试”的东西完全可以正常工作。不确定您对未声明变量的含义。在现有代码中,模型是在建立连接之前建立的,我只是尝试将mongoose.connect(...)部分放在底部,它仍然错误。
  • 那是不同的。索引定义是错误的。但这“是一个人为的案例”,除非您在这种情况下特别需要捕获该特定错误,否则您可以很容易地避免一开始就不这样做。事实上,猫鼬文档建议您“关闭自动索引”并使用“特定代码”来创建任何索引。此外,这不是您最初发布的问题。

标签: node.js mongodb mongoose promise mongoose-schema


【解决方案1】:

你得到这个的原因是由于定义了重复的索引。

你应该只有这些行之一。

TestSchema.index({'num': 1}, { sparse: true })
TestSchema.index({'num': 1}, { sparse: false })

Unhandled promise 实际上来自与createIndex 相关的node-mongodb-native 中的拒绝。这不会在 mongoose 中公开,以便您捕获错误。

可能的逻辑推理很简单,就是您的架构定义中永远不应该有错误。这是在开发过程中可能/应该很容易发现的东西,以后不会重复。

【讨论】:

  • 修复了这个问题(参见编辑后的代码),但仍然没有发现错误。原来的语法只是多余的(因为我很困惑),无论如何,实际上并不是错误的。
  • 你运行的是什么版本的猫鼬?
  • mongoose@4.12.4
  • 是的,我也有同样的想法。但实际上,您的应用程序永远不应该这样做。由于您错误地定义了架构,因此您总是会在使用之前修复此错误,并且它不会在您的应用运行时出现。
  • 我还认为,即使您确实找到了一个“解决方案”来捕获它,将其添加到您的代码中也是错误的,就像我说的那样,它应该始终 在提交/部署等之前修复。
【解决方案2】:

在环顾四周并找到this article 之后,这个问题的一个可能答案可能是添加以下行:

process.on('unhandledRejection', function(error) {
  // do something with this error
})

这样做意味着此警告消失:

(node:26795) [DEP0018] DeprecationWarning: Unhandled promise rejections 
are deprecated. In the future, promise rejections that are not handled 
will terminate the Node.js process with a non-zero exit code.

但我实际上并不知道这会阻止 Node.js 进程退出。

【讨论】:

  • 这不是一个好主意,因为它将适用于您应用中所有未处理的拒绝。这不是你想要的,因为在大多数情况下,你想要捕捉承诺,而不是忽略它们。
  • 是的,我基本上同意这是一个坏主意。我将使用process.on('unhandledRejection', ...) 功能更好地跟踪此类 unhandledRejection,例如通过打印堆栈,如果生产中存在 unhandledRejection,也可以通过电子邮件发送给我。
猜你喜欢
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 1970-01-01
  • 1970-01-01
  • 2020-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多