NodeJS未处理的承诺拒绝

我有一个方法getModel(kind) ,在NodeJS中返回一个数据存储数据模型。

我在getModel(kind)方法中做了一个简单的type-o,发现了未被捕获的承诺拒绝的根本问题。

我如何更新代码来捕获未来的未捕获的exception?

调用getModel:

 //Save the data to the database getModel('transferrequest').create(TransferRequestNew, (err, savedData) => { if (err) { console.log('Transfer Request New unable to create new entity. Error message: ', err); next(err); return; } console.log('savedData: ', savedData); res.redirect(`${req.baseUrl}/history`); }); 

getModel函数:

 function getModel(kind) { const model = __modelsdir+'/model-'+__databackend+kind; return require(model); } 

使用getModel.create调用创build方法:

 function create (data, cb) { update(null, data, cb); } 

未处理的错误:

(node:31937)UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝ID:1):错误:找不到模块'/ mypath / projectname / models / model-datastoretransferrequest'

首先,我要说的是dynamic的require是让自己陷入困境的一种方式。 让我分两个部分来回答问题,强调应该避免的原因,并提出一些解决scheme。


潜在的问题

  1. 运行时的同步加载

    require是一个同步操作,而众所周知,这样的操作阻塞了Event Loop。 想象一下,相当大量的用户同时使用你的应用程序,并且循环延迟高于合理值或者至less开始引起性能问题。

  2. 很难testing这样的dynamic模块

    如果没有适当的testing覆盖,你如何保证你的应用程序足够稳定? 随着dynamic要求,它成为一个不平凡的任务。 这导致了另一个问题 – 你真的有这么多的数据模型,他们需要dynamic创build和加载? 如果不是这样,那么可以使你的工作更加适应定义明确的数据模型,而不是“魔术”加载容易出错。 此外,不要忘记循环依赖和其他可怕的可憎的事物,直到import时刻才会保持沉默。

  3. 这种应用的总体devise

    有必要阅读ESLint关于global-require 主题 ,了解为什么默认情况下不允许使用各种规则集(例如Airbnb)。 但是你实际上提到了你自己:

    我在getModel(kind)方法中做了一个简单的type-o,发现了未被捕获的承诺拒绝的根本问题。

    如果这足以打破你的应用程序,这个应用程序可以被认为是强大的? 这与原始string作为参数是一样的:应该让它们成为常量或者以函数本身的forms出现,摆脱难以debugging的运行时错误,以便在启动时换取简单的语法错误。


可能的解决scheme

明确要求的模型

创build表示数据结构的明确定义的对象结构,并从一个聚集的index.js文件中显式加载它们:

 // models/transfer-request.js class TransferRequest { create(instance, cb) { // Implementation... } } module.exports = TransferRequest; // models/index.js const TransferRequest = require('./transfer-request.js'); // Other models requires... module.exports = { TransferRequest, // Other models exports... }; 

使用Factory创build实例

如果您仍想继续使用类似于您现在所拥有的function,请使用标准模式创build模型工厂:

 class ModelFactory { constructor(model){ switch(model) { case 'transferrequest': // Implementation of TransferRequest object creation... break; case 'othertransferrequest': // Implementation of OtherTransferRequest object creation... break; default: throw new Error('Unknown class'); } } } 

用清晰可见的方式创build实际的模型对象是时代和好时代,在代码中定义明确,而不是用dynamic加载掩盖可能的选项。

是的,如果你还想在运行时require ,只需使用try/catch来处理拒绝。

这只是一个可以解决这个问题的方法,但可能会有一些更好的方法。 你为什么不试试赶上要求的声明? 我已经testing了这一点,这工作得很好:

 function getModel(kind, cb) { var model = __dirname + kind; try { var requiredModel = require(model); return cb(null, requiredModel) } catch (e) { return cb(new Error("model not found!"), null); } } 

我用__dirnametesting了这个,但是这不应该有所作为。

顺便说一句:这不应该显示最佳做法error handling,只是在我的rest时间写下来。