我试图在这里搜索类似的问题,但令人惊讶的是还没有找到一个已发布的问题。
我使用expressjs v4框架,我正在构建我的路线:
'use strict';
let express = require('express');
let router = express.Router();
let users = require('./modules/users');
router.post('/',users.add);
router.put('/edit/:id',users.edit);
如您所见,我需要let users = require('./modules/users')
现在users
模块看起来像这样:
'use strict';
let usersDbModule = require('...');
let users = {
'add': (req, res, next) => {
let callback = (err, record) => {
//...do something
users.function1(record)
}
usersDbModule.save(req, callback);
},
'function1': (record) => {
users.function2()
},
'function2': () => {
//...do something with next() function
}
}
您可以注意到,第一个代码块中的路由器正在使用模块的add
功能。 add
函数它是一个标准的快速中间件函数,但现在事情变得越来越复杂了。
正如您所看到的,add
函数有next
作为参数之一,现在我正在执行一些来自不同函数的复杂回调调用,并且让我们在最后,我想在next
中致电function2
。
我的问题是,在同一模块内的不同回调函数之间传递req
,res
和next
参数的最佳方法是什么。
我想出了3种不同的方法:
方法1:
如有必要,请将req
,res
或next
传递给链中的所有功能,因此在这种情况下,我必须将next
传递给callback
而不是function1
而不是function1
到function2
。
在我看来,这不是最好的方式,难以维护,阅读和测试。
方法2:
将function1
和function2
与add
中的闭包包裹在一起,传递所有必要的参数。在这种特殊情况下,我只需要通过function2
封闭next
,所以它看起来像这样:
'add': (req, res, next) => {
users.function2(next);
//....rest of the code of the function add
}
而不是function2
本身:
'function2': (next) => {4
return () => {
//...now I have access to next here
// without a need to pass it to each and every
// function in the chain
}
}
方法3:
将所有必要的函数/变量附加到res.locals
并仅传递res
个对象。
它与Method 1
完全相同,所以我个人赞成Method 2
,但不确定它是否不会使代码的可读性降低,也许还有一些其他问题有了它,还没有在团队的生产和开发环境中测试它。
我真的很想听听你们在你们的项目/团队中使用了什么以及它们如何发挥作用。任何偏好,最佳实践,最佳模式?请分享,我真的想知道最好的方法。
也许还有更好的方法吗?
所有反馈都非常感谢!
现实生活中的例子:
function1
&的示例用法function2
可能更多......
假设我们有一个从外部API获取数据的适配器,而不是将数据保存到数据库中,并返回响应。我们还假设从API返回的数据在5s后过期。如果客户端在5s范围内命中路由,则如果调用之间的时间较长,它将从数据库获取数据,而不是重复调用API的操作。
这当然比function1
和function2
更复杂。它需要很多回调函数,包括来自适配器和数据库,还有单独的函数,用于从数据库中获取数据,适配器,将数据保存到数据库中,最终从数据库中删除数据,它至少提供4个回调函数已经
答案 0 :(得分:0)
我认为mix express和app逻辑不是一个好主意。 我在我的项目中使用下一个方法
// middlewares/auth.js
// Example middleware
exports.isAdmin = function (req, res, next) {
if (smth-admin-check)
next();
else
next (new Error(403));
}
// routes/index.js
// Include only modules from /routes
let user = require('./user');
let auth = require('../middlewares/auth');
...
app.get('/user/:id(\\d+)', user.get);
app.post('/user', auth.isAdmin, user.post); // only admin can add user
// routes/user.js
// Call model methods and render/send data to browser
// Don't know about db
let User = require('/models/user');
...
exports.get = function(req, res, next) {
let id = req.params.id;
// I cache most data in memory to avoid callback-hell
// But in common case code like below
User.get(id, function(err, u) {
if (!u)
return next(new Error('Bad id'));
... render page or send json ...
});
}
...
exports.post = function(req, res, next) { ... }
// models/user.js
// Encapsulate user logic
// Don't use any express features
let db = require('my-db');
...
class User {
get(id, callback) { ... }
add(data, callback) { ... } // return Error or new user
...
}