Passer des variables au middleware suivant en utilisant next () dans Express.js

201

Eh bien, ma question est que je veux passer une variable du premier middleware à un autre middleware, et j'ai essayé de le faire, mais il y avait " req.somevariableest une donnée comme 'non définie'".


//app.js
..
app.get('/someurl/', middleware1, middleware2)
...

////middleware1
...
some conditions
...
res.somevariable = variable1;
next();
...

////middleware2
...
some conditions
...
variable = req.somevariable;
...
user2791897
la source
Devrait marcher. À moins qu'il ne s'agisse d'une faute de frappe dans la question, vous échouerez probablement car vous attribuez la valeur à resdans middleware1 et essayez de l'obtenir reqdans middleware2.
Andreas Hultgren
Thankz @AndreasHultgren
user2791897
Local variables are available in middleware via req.app.locals expressjs.com/pt-br/api.html#app.locals
Ronnie Royston

Réponses:

202

Attachez votre variable à l' reqobjet, non res.

Au lieu de

res.somevariable = variable1;

Avoir:

req.somevariable = variable1;

Comme d'autres l'ont souligné, res.localsc'est la façon recommandée de transmettre des données via un middleware.

Amberlamps
la source
13
utilisez res.locals.variable = var; voir l'autre réponse
godzsa
1
pour récupérer la variable, utilisez req.res.locals.variable dans la prochaine fonction middleware
William Wu
3
@WilliamWu c'est res.localspas req.res.locals.
cchamberlain
2
res.locals.myVarest la voie à suivre.
jasonseminara
449

C'est à cela que sert l' objet res.locals . La définition de variables directement sur l'objet de demande n'est ni prise en charge ni documentée. res.locals est garanti de tenir l'état pendant la durée d'une demande.

res.locals

Un objet qui contient des variables locales de réponse étendues à la demande, et donc disponible uniquement pour les vues rendues pendant ce cycle de demande / réponse (le cas échéant). Sinon, cette propriété est identique à app.locals.

Cette propriété est utile pour exposer des informations au niveau de la demande telles que le nom du chemin de la demande, l'utilisateur authentifié, les paramètres utilisateur, etc.

app.use(function(req, res, next) {
    res.locals.user = req.user;  
    res.locals.authenticated = !req.user.anonymous;
    next();
});

Pour récupérer la variable dans le middleware suivant:

app.use(function(req, res, next) {
    if (res.locals.authenticated) {
        console.log(res.locals.user.id);
    }
    next();
});
cchamberlain
la source
67
Je ne sais pas pourquoi ce n'est pas la réponse acceptée, c'est la façon documentée de définir des variables à partir du middleware tout au long d'une demande.
Sam Holmes
11
res.locals est destiné à être utilisé par des vues qui sont éventuellement restituées pendant le cycle de vie de la demande, c'est ce que dit la documentation. Si vous n'utilisez pas les vues, il est exagéré de mettre des choses sur l'objet local et ce n'est pas la convention. Dans ces cas, j'ai tendance à encourager les gens à respecter la convention afin que nous puissions réduire la charge cognitive tout en apprenant des concepts comme Express ou demander des cycles de vie.
real_ate
2
@real_ate qui est l'utilisation principale de res.locals, mais il ne répond pas à la question des OP. La transmission de variables de portée de demande au futur middleware est parfois une nécessité, les fois où je l'ai eue concernent généralement l'authentification des utilisateurs dans un middleware précoce qui définit les revendications qui sont acheminées dans un middleware en aval.
cchamberlain
14
La documentation express pour l'écriture de middleware définit des variables sur l' reqobjet expressjs.com/en/guide/writing-middleware.html . Regardez la sectionMiddleware function requestTime
Catfish
3
@goonerify ce n'est heureusement pas comment fonctionne la réponse. Les réponses sont transmises en appelant une propriété fonctionnelle de l'objet de réponse telle que res.json({}), etc. res.localsn'est disponible sur le serveur principal que pendant la durée de la demande. expressjs.com/en/5x/api.html
cchamberlain
22

Je ne pense pas que la meilleure pratique passera une variable comme req.YOUR_VAR. Vous voudrez peut-être envisager req.YOUR_APP_NAME.YOUR_VARou req.mw_params.YOUR_VAR.

Cela vous aidera à éviter d'écraser d'autres attributs.

Mise à jour du 31 mai 2020

res.locals est ce que vous recherchez, l'objet est limité à la demande.

Un objet qui contient des variables locales de réponse étendues à la demande, et donc disponible uniquement pour les vues rendues pendant ce cycle de demande / réponse (le cas échéant). Sinon, cette propriété est identique à app.locals.

Cette propriété est utile pour exposer des informations au niveau de la demande telles que le nom du chemin de la demande, l'utilisateur authentifié, les paramètres utilisateur, etc.

Doron Segal
la source
2
Comment proposez-vous de définir req.YOUR_APP_NAME = {}initialement? Vous essayez juste d'écrire pour req.YOUR_APP_NAME.someVarvous obtenir une erreur car elle req.YOUR_APP_NAMEn'est pas encore définie.
Kousha
2
@Kousha Vous pouvez écrire un middleware de routeur en haut de votre script de routage:router.use(function(req,res,next){req.YOUR_APP_NAME = {};next()})
Tomas
existe-t-il un moyen de le passer en paramètre avec la fonction next ()? comme suivant (myObj)
philx_x
1
@Kousha - Votre erreur non définie n'a rien à voir avec express, c'est que vous essayez d'assigner une propriété à un objet qui n'existe pas. Pour ce faire, vous utilisez généralement req.APP_NS = req.APP_NS || {}; req.APP_NS.somevar = 'value'.
cchamberlain
1
@philx_x, si vous passez un paramètre à la nextfonction, cela déclenchera le gestionnaire d'erreur express et disparaîtra. consultez les documents.
Merl
7

C'est parce que reqet ressont deux objets différents.

Vous devez rechercher la propriété sur le même objet auquel vous l'avez ajouté.

SLaks
la source
3

L'astuce est assez simple ... Le cycle de demande est toujours bien vivant. Vous pouvez simplement ajouter une nouvelle variable qui créera un temporaire, appelant

app.get('some/url/endpoint', middleware1, middleware2);

Puisque vous pouvez gérer votre demande dans le premier middleware

(req, res, next) => {
    var yourvalue = anyvalue
}

Dans le middleware 1, vous gérez votre logique et stockez votre valeur comme ci-dessous:

req.anyvariable = yourvalue

Dans le middleware 2, vous pouvez récupérer cette valeur à partir du middleware 1 en procédant comme suit:

(req, res, next) => {
    var storedvalue = req.yourvalue
}
Delino
la source
1

Comme mentionné ci-dessus, res.locals est un bon moyen (recommandé) de le faire. Voir ici pour un didacticiel rapide sur la façon de procéder dans Express.

nax3t
la source