简体   繁体   English

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

[英]Best way to pass route params between callbacks in expressjs

I've tried to search for a similar problem on here but suprisingly couldn't find one posted already. 我试图在这里搜索类似的问题,但令人惊讶的是找不到已发布的问题。

I use expressjs v4 framework and I'm constructing my routes like this: 我使用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);

As you can see above, I'm requiring let users = require('./modules/users') 如上所示,我要求let users = require('./modules/users')

Now the users module looks (let's say) like this: 现在, 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
    }
}

You can notice, that router from the first code block is using module's add function. 您可以注意到,第一个代码块中的路由器正在使用模块的add函数。 add function it's a standard express middleware function but now the things are getting more complicated. add功能它是一个标准的快速中间件功能,但现在事情变得越来越复杂。

As you can see, add function has next as one of the params, now I'm doing some complex callbacks calls from different functions and let's say that in the end I want to call next in function2 . 正如你所看到的, add函数next是params之一,现在我正在做一些来自不同函数的复杂回调函数,让我们说最后我想在function2调用next

My question is, what is the best way of passing req , res and next params between different callback functions within the same module. 我的问题是,在同一模块中的不同回调函数之间传递reqresnext params的最佳方法是什么。

I come up with 3 different methods of doing it: 我想出了3种不同的方法:

Method 1: Pass req , res or next if necessary around to all the functions in the chain so in this case I would have to pass next to callback than to function1 and than from function1 to function2 . 方法1:通过reqresnext如果有必要向周围链中的所有功能,所以在这种情况下,我将不得不通过nextcallback ,而不是function1 ,比从function1function2

Not the best way in my opinion, difficult to maintain, read and probably test as well. 在我看来,这不是最好的方式,难以维护,阅读和测试。

Method 2: Wrap function1 and function2 with closures in the add passing all the necessary params. 方法2:function1function2与在封闭add通过所有必要的PARAMS。 In this particular case I would have to wrap only function2 with closure passing next so it would looks something like this: 在这个特殊的情况下,我将只包含function2next传递闭包,所以它看起来像这样:

'add': (req, res, next) => {
    users.function2(next);
    //....rest of the code of the function add
}

And than the function2 itself: 而且比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
   }
} 

Method 3: 方法3:

Append all the necessary functions/variables to res.locals and pass only res object around. 将所有必要的函数/变量附加到res.locals并仅传递res对象。

It has exactly the same problem as Method 1 so I would personally be in favour of Method 2 but not sure if it doesn't make the code less readable and maybe there are some other problems with it, haven't tested it in production nor in development environment with the team. 它与Method 1有完全相同的问题所以我个人会赞成Method 2但不确定它是否会使代码不易读取,也许还有一些其他问题,没有在生产中测试过,也没有在团队的开发环境中。


I would really like to hear what are you guys using and how it plays in your projects/teams. 我真的很想听听你们在你们的项目/团队中使用了什么以及它们如何发挥作用。 Any preferences, best practices, best patterns ? 任何偏好,最佳实践,最佳模式? Please share, I really want to know what's the best way. 请分享,我真的想知道什么是最好的方式。

Maybe there is even better way of doing it ? 也许还有更好的方法吗?

All feedback greatly appreciated! 所有反馈非常感谢!


Real life example: 真人生活的例子:

Example usage for function1 & function2 and possibly more... function1function2示例用法以及可能更多......

Let's say we have an adapter that fetches data from an external API, than it needs to save the data into a database, and return a response. 假设我们有一个从外部API获取数据的适配器,而不是将数据保存到数据库中,并返回响应。 Let's also assume that the data returned from the API expires after 5s. 我们还假设从API返回的数据在5s后过期。 If the client hits the route within 5s span, it gets the data from the database, if time between calls was longer, than it repeats the operation calling the API. 如果客户端在5s范围内命中路由,则如果调用之间的时间较长,则它从数据库获取数据,而不是重复调用API的操作。

This would be of course more complicated than just function1 and function2 . 这当然比function1function2更复杂。 It would require a lot of callback functions, both from the adapter and the database, also separate functions for fetching data from the database, adapter, saving data into a database, and eventually deleting data from the database, it gives at least 4 callback functions already. 它需要很多回调函数,包括来自适配器和数据库,还有单独的函数,用于从数据库中获取数据,适配器,将数据保存到数据库中,最终从数据库中删除数据,它至少提供4个回调函数已经。

I think that mix express and app logic is not a good idea. 我认为mix express和app逻辑并不是一个好主意。 I use next way in my project 我在我的项目中使用下一个方法

// 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
   ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM