Przekazywanie zmiennych do następnego oprogramowania pośredniego za pomocą next () w Express.js

200

Cóż, moje pytanie brzmi: chcę przekazać jakąś zmienną z pierwszego oprogramowania pośredniego do innego oprogramowania pośredniego i próbowałem to zrobić, ale było „ req.somevariablepodano jako„ niezdefiniowane ””.


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

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

////middleware2
...
some conditions
...
variable = req.somevariable;
...
użytkownik2791897
źródło
Powinno działać. Chyba że jest to literówka w pytaniu, które prawdopodobnie nie powiedzie się, ponieważ przypisujesz wartość do resw oprogramowaniu pośrednim 1 i próbujesz uzyskać ją z reqoprogramowania pośredniego 2.
Andreas Hultgren,
Thankz @AndreasHultgren
user2791897 18.09.13
Local variables are available in middleware via req.app.locals expressjs.com/pt-br/api.html#app.locals
Ronnie Royston

Odpowiedzi:

202

Nie dołączaj swojej zmiennej do reqobiektu res.

Zamiast

res.somevariable = variable1;

Mieć:

req.somevariable = variable1;

Jak zauważyli inni, res.localsjest to zalecany sposób przesyłania danych przez oprogramowanie pośrednie.

Amberlampy
źródło
13
użyj res.locals.variable = var; zobacz drugą odpowiedź
godzsa
1
aby pobrać zmienną, użyj req.res.locals.variable w następnej funkcji oprogramowania pośredniego
William Wu
3
@WilliamWu jego res.locals, nie req.res.locals.
cchamberlain
2
res.locals.myVarjest droga.
jasonseminara
447

Do tego służy obiekt res.locals . Ustawianie zmiennych bezpośrednio w obiekcie żądania nie jest obsługiwane ani dokumentowane. res.locals gwarantuje utrzymanie stanu przez cały okres ważności żądania.

res.locals

Obiekt zawierający lokalne zmienne odpowiedzi o zasięgu do żądania, a zatem dostępny tylko dla widoków wyświetlanych podczas tego cyklu żądania / odpowiedzi (jeśli istnieje). W przeciwnym razie ta właściwość jest identyczna z app.locals.

Ta właściwość jest przydatna do ujawniania informacji na poziomie żądania, takich jak nazwa ścieżki żądania, uwierzytelniony użytkownik, ustawienia użytkownika i tak dalej.

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

Aby pobrać zmienną z następnego oprogramowania pośredniego:

app.use(function(req, res, next) {
    if (res.locals.authenticated) {
        console.log(res.locals.user.id);
    }
    next();
});
cchamberlain
źródło
66
Nie wiem, dlaczego nie jest to akceptowana odpowiedź, jest to udokumentowany sposób ustawiania zmiennych z oprogramowania pośredniego podczas żądania.
Sam Holmes,
11
res.locals jest przeznaczony do użycia w widokach , które ostatecznie są renderowane podczas cyklu życia żądania, tak mówi dokumentacja. Jeśli nie korzystasz z widoków jest przesadą, aby umieścić rzeczy na obiekcie mieszkańców i to nie konwencja. W takich przypadkach staram się zachęcać ludzi do przestrzegania konwencji, abyśmy mogli zmniejszyć obciążenie poznawcze podczas uczenia się takich pojęć, jak Express lub cykl życia.
real_ate
2
@real_ate to podstawowe użycie res.locals, jednak nie odnosi się do pytania OP. Przekazywanie zmiennych o zasięgu żądania do przyszłego oprogramowania pośredniego jest czasem koniecznością, czasem, kiedy to pojawiło się, zwykle dotyczy uwierzytelnienia użytkownika we wczesnym oprogramowaniu pośrednim, które określa żądania, które są kierowane w dalszym oprogramowaniu pośrednim.
cchamberlain
14
Dokumentacja ekspresowa do pisania oprogramowania pośredniego ustawia zmienne w reqobiekcie expressjs.com/en/guide/writing-middleware.html . Spójrz na sekcjęMiddleware function requestTime
Sum
2
@goonerify to na szczęście nie działa odpowiedź. Odpowiedzi są przesyłane przez wywołanie właściwości funkcjonalnej obiektu odpowiedzi, takiego jak res.json({})itp., res.localsJest dostępna tylko na zapleczu przez cały czas trwania żądania. expressjs.com/en/5x/api.html
cchamberlain
22

Nie sądzę, że najlepszą praktyką będzie przekazywanie zmiennej takiej jak req.YOUR_VAR. Możesz rozważyć req.YOUR_APP_NAME.YOUR_VARlub req.mw_params.YOUR_VAR.

Pomoże Ci to uniknąć zastąpienia innych atrybutów.

Aktualizacja 31 maja 2020 r

res.locals jest tym, czego szukasz, zakres obiektu jest zgodny z żądaniem.

Obiekt zawierający lokalne zmienne odpowiedzi o zasięgu do żądania, a zatem dostępny tylko dla widoków wyświetlanych podczas tego cyklu żądania / odpowiedzi (jeśli istnieje). W przeciwnym razie ta właściwość jest identyczna z app.locals.

Ta właściwość jest przydatna do ujawniania informacji na poziomie żądania, takich jak nazwa ścieżki żądania, uwierzytelniony użytkownik, ustawienia użytkownika i tak dalej.

Doron Segal
źródło
2
Jak sugerujesz ustawienie req.YOUR_APP_NAME = {}początkowo? Po prostu spróbuj napisać do req.YOUR_APP_NAME.someVarciebie, pojawi się błąd, który req.YOUR_APP_NAMEnie został jeszcze zdefiniowany.
Kousha
2
@Kousha Możesz napisać oprogramowanie pośredniczące routera u góry skryptu routingu:router.use(function(req,res,next){req.YOUR_APP_NAME = {};next()})
Tomas
czy istnieje sposób, aby przekazać go jako parametr za pomocą funkcji next ()? jak następny (myObj)
philx_x
1
@Kousha - Twój niezdefiniowany błąd nie ma nic wspólnego z express, próbujesz przypisać właściwość do obiektu, który nie istnieje. Zazwyczaj by to zrobić, użyłbyś tego req.APP_NS = req.APP_NS || {}; req.APP_NS.somevar = 'value'.
cchamberlain
1
@phxx_x, jeśli przekażesz dowolny parametr do nextfunkcji, uruchomi on ekspresową procedurę obsługi błędów i odpadnie. sprawdź dokumenty.
Merl
7

To dlatego, że reqi resto dwa różne obiekty.

Musisz poszukać właściwości na tym samym obiekcie, do którego ją dodałeś.

SLaks
źródło
3

Sztuczka jest dość prosta ... Cykl zapytań wciąż jest całkiem żywy. Możesz po prostu dodać nową zmienną, która utworzy tymczasowe wywołanie

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

Ponieważ możesz obsłużyć żądanie w pierwszym oprogramowaniu pośrednim

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

W oprogramowaniu pośrednim 1 zarządzasz logiką i przechowujesz swoją wartość jak poniżej:

req.anyvariable = yourvalue

W oprogramowaniu pośrednim 2 można przechwycić tę wartość z oprogramowania pośredniego 1, wykonując następujące czynności:

(req, res, next) => {
    var storedvalue = req.yourvalue
}
Delino
źródło
1

Jak wspomniano powyżej, res.locals jest dobrym (zalecanym) sposobem na zrobienie tego. Zobacz tutaj na szybki tutorial jak to zrobić w Express.

nax3t
źródło