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。
潜在的问题
-
运行时的同步加载
require
是一个同步操作,而众所周知,这样的操作阻塞了Event Loop。 想象一下,相当大量的用户同时使用你的应用程序,并且循环延迟高于合理值或者至less开始引起性能问题。 -
很难testing这样的dynamic模块
如果没有适当的testing覆盖,你如何保证你的应用程序足够稳定? 随着dynamic要求,它成为一个不平凡的任务。 这导致了另一个问题 – 你真的有这么多的数据模型,他们需要dynamic创build和加载? 如果不是这样,那么可以使你的工作更加适应定义明确的数据模型,而不是“魔术”加载容易出错。 此外,不要忘记循环依赖和其他可怕的可憎的事物,直到import时刻才会保持沉默。
-
这种应用的总体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); } }
我用__dirname
testing了这个,但是这不应该有所作为。
顺便说一句:这不应该显示最佳做法error handling,只是在我的rest时间写下来。