在expressjs中回调之间传递路由参数的最佳方法

时间:2016-09-07 11:07:53

标签: javascript node.js express callback

我试图在这里搜索类似的问题,但令人惊讶的是还没有找到一个已发布的问题。

我使用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

我的问题是,在同一模块内的不同回调函数之间传递reqresnext参数的最佳方法是什么。

我想出了3种不同的方法:

方法1: 如有必要,请将reqresnext传递给链中的所有功能,因此在这种情况下,我必须将next传递给callback而不是function1而不是function1function2

在我看来,这不是最好的方式,难以维护,阅读和测试。

方法2:function1function2add中的闭包包裹在一起,传递所有必要的参数。在这种特殊情况下,我只需要通过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的操作。

这当然比function1function2更复杂。它需要很多回调函数,包括来自适配器和数据库,还有单独的函数,用于从数据库中获取数据,适配器,将数据保存到数据库中,最终从数据库中删除数据,它至少提供4个回调函数已经

1 个答案:

答案 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
   ...
}