Express'te “sonraki” parametresi ne için kullanılır?


296

Bunun gibi basit bir kod bloğunuz olduğunu varsayalım:

app.get('/', function(req, res){
    res.send('Hello World');
});

Bu fonksiyon iki parametre, yer alır reqve restalebi temsil eden ve yanıt sırasıyla nesneler.

Diğer yandan, üçüncü bir parametreye sahip başka işlevler de vardır next. Örneğin, aşağıdaki koda bir göz atalım:

app.get('/users/:id?', function(req, res, next){ // Why do we need next?
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next(); // What is this doing?
    }
});

Amacının ne next()olduğunu veya neden kullanıldığını anlayamıyorum. Bu örnekte kimlik yoksa, nextgerçekte ne yapıyor?


13
Ardından, bir sonraki rota işleyicisinin isteği işlemesine izin verir. Bu durumda, kullanıcı kimliği varsa, büyük olasılıkla res.sendisteği tamamlamak için kullanılır . Yoksa, büyük olasılıkla bir hata verecek ve isteği tamamlayacak başka bir işleyici vardır.
Dominic Barnes

1
Bu yüzden next () çağırarak giriş app.js dosyasındaki bir sonraki rota olarak arayacak bir app.post('/login',function(req,res))sonra var diyorsun app.get('/users',function(req,res)) ?
Menztrual

2
Hayır, Express.js belgelerinin bu bölümüne başvurmalısınız: expressjs.com/guide.html#passing-route control
Dominic Barnes

3
Temel olarak, çalıştırılacak bir sonraki rota, isteğin URL'sinin eşleştiği başka bir rota olacaktır. Bu durumda, başka bir rota üzerinden kaydedildiyse app.get("/users"), yukarıdaki işleyici bir sonraki çağrılırsa çalıştırılır.
Dominic Barnes

3
Sonraki temelde sadece bir geri arama.
Jonathan Ong

Yanıtlar:


266

Kontrolü bir sonraki eşleşen yola geçirir . Örneğin, verdiğiniz örnekte, idverilmişse kullanıcıyı veritabanında arayabilir ve atayabilirsiniz req.user.

Aşağıda, aşağıdaki gibi bir rotanız olabilir:

app.get('/users', function(req, res) {
  // check for and maybe do something with req.user
});

/ Users / 123 önce örneğinizdeki rotayla eşleşeceğinden, önce kullanıcıyı kontrol edip bulacaktır 123; o /userszaman bunun sonucu ile bir şeyler yapabilir.

Bence, rota ara katman yazılımı daha esnek ve güçlü bir araçtır. UsersAsync ile bir model varsayarak, bu şekilde gösterilen örneği modellemeye meyilli olacağım findOne():

function loadUser(req, res, next) {
  if (req.params.userId) {
    Users.findOne({ id: req.params.userId }, function(err, user) {
      if (err) {
        next(new Error("Couldn't find user: " + err));
        return;
      }

      req.user = user;
      next();
    });
  } else {
    next();
  }
}

// ...

app.get('/user/:userId', loadUser, function(req, res) {
  // do something with req.user
});

app.get('/users/:userId?', loadUser, function(req, res) {
  // if req.user was set, it's because userId was specified (and we found the user).
});

// Pretend there's a "loadItem()" which operates similarly, but with itemId.
app.get('/item/:itemId/addTo/:userId', loadItem, loadUser, function(req, res) {
  req.user.items.append(req.item.name);
});

Bu şekilde akışı kontrol edebilmek oldukça kullanışlıdır. Belirli sayfaların yalnızca yönetici bayrağı olan kullanıcılar tarafından kullanılabilir olmasını isteyebilirsiniz:

/**
 * Only allows the page to be accessed if the user is an admin.
 * Requires use of `loadUser` middleware.
 */
function requireAdmin(req, res, next) {
  if (!req.user || !req.user.admin) {
    next(new Error("Permission denied."));
    return;
  }

  next();
}

app.get('/top/secret', loadUser, requireAdmin, function(req, res) {
  res.send('blahblahblah');
});

Umarım bu size biraz ilham verir!


Öyle diyebilirsin! Bu tür bir şeyi rota ara katman yazılımı ile yapmaya daha meyilli olurum , çünkü mantığı belirli bir rota sırasına veya belirli URI yapılarına bağlamaz.
Asherah

5
neden bazen bazen yok Sonraki (return) ama
John

6
@John: Dönüş değeri aslında yok sayılır; Tekrar aramamý sağlamak için oraya geri dönmek istiyorum next(). Sadece kullansaydım aynı olurdu next(new Error(…)); return;.
Asherah

1
@ level0: dönüş değeri yoksayılır; kısaca düşünebilirsiniz next(new Error(…)); return;. Bir değer iletirseknext , tek taraflı olarak bir hata olarak kabul edilir . Ekspres koda çok fazla bakmadım, ama etrafı kazın ve ihtiyacınız olanı bulacaksınız :)
Asherah

1
@ level0: (ben değiştim return next(…);için next(…); return;daha az kafa karıştırıcı yani.)
Aşera

87

Sonraki () problemim de vardı, ama bu yardımcı oldu

var app = require("express")();

app.get("/", function(httpRequest, httpResponse, next){
    httpResponse.write("Hello");
    next(); //remove this and see what happens 
});

app.get("/", function(httpRequest, httpResponse, next){
    httpResponse.write(" World !!!");
    httpResponse.end();
});

app.listen(8080);

3
Çok özlü! Teşekkürler! Ama ikincisinin .getdeğil, birincinin çağrıldığından nasıl emin olabilirsiniz ?
JohnnyQ

18
@JohnnyQ Yukarıdan aşağıya doğru icra olacak
Tapash

@JohnnyQ Güzergâhlar beyan edildiği şekilde alınır. Eşleşen iki rota varsa, program akışında ilk karşılaşılan rota seçilir.
Shubham Anand

59

Anlamadan önce next, ayrıntılı olarak olmasa da, düğümde İstek-Yanıt döngüsü hakkında küçük bir fikriniz olması gerekir. Belirli bir kaynak için HTTP isteğinde bulunmanızla başlar ve kullanıcıya bir yanıt gönderdiğinizde, yani res.send ('Merhaba Dünya') gibi bir şeyle karşılaştığınızda sona erer.

çok basit bir örneğe bakalım.

app.get('/hello', function (req, res, next) {
  res.send('USER')
})

Burada next () işlevine ihtiyacımız yok, çünkü resp.send çevrimi sona erdirecek ve kontrolü yol orta yazılımına geri verecektir.

Şimdi başka bir örneğe bakalım.

app.get('/hello', function (req, res, next) {
  res.send("Hello World !!!!");
});

app.get('/hello', function (req, res, next) {
  res.send("Hello Planet !!!!");
});

Burada aynı yol için 2 ara katman fonksiyonuna sahibiz. Ama her zaman ilkinden yanıt alacaksınız. Çünkü bu ilk olarak ara katman yığınına monte edilir ve res.send döngüsü sona erdirir.

Ama ya hep "Merhaba Dünya !!!!" yanıt. Bazı koşullar için "Merhaba Gezegen !!!!" tepki. Yukarıdaki kodu değiştirelim ve ne olacağını görelim.

app.get('/hello', function (req, res, next) {
  if(some condition){
    next();
    return;
  }
  res.send("Hello World !!!!");  
});

app.get('/hello', function (req, res, next) {
  res.send("Hello Planet !!!!");
});

nextBurada ne işi var. Ve evet küfürleriniz olabilir. Koşul doğruysa ilk ara katman işlevini atlayacak ve bir sonraki ara katman işlevini çağıracak ve "Hello Planet !!!!"yanıtı alacaksınız .

Böylece, daha sonra kontrolü ara katman yığınındaki bir sonraki işleve geçirin.

İlk ara katman yazılımı işlevi herhangi bir yanıt göndermez ancak bir parça mantık yürütürse ve sonra ikinci ara katman işlevinden geri yanıt alırsanız ne olur.

Aşağıdaki gibi bir şey: -

app.get('/hello', function (req, res, next) {
  // Your piece of logic
  next();
});

app.get('/hello', function (req, res, next) {
  res.send("Hello !!!!");
});

Bu durumda, her iki ara katman işlevinin de çağrılması gerekir. Bu nedenle, ikinci ara katman işlevine erişmenin tek yolu next ();

Bir sonrakini aramazsanız ne olur. İkinci ara katman işlevinin otomatik olarak çağrılmasını beklemeyin. İlk işlevi çağırdıktan sonra isteğiniz asılı kalır. İkinci işlev asla çağrılmaz ve yanıtı geri alamazsınız.


Yani next()gerçekleştirdiği bir gibi gotosabit kablolu etiketle? Yani, üçüncü snippet'inizde, bir kez aradığınızda next(), res.send("Hello World !!!!"); asla idam edilemez mi? Ben her zaman aynı yürütme ağacında kodu vardı return;sonra nextaramalar vardı fark ettim ... Sanırım her zaman sadece ekspres check-in olabilir, ha? / onun metin editörü yanına koşar;)
ruffin

@ ruffin yes to go'yu düşünebilirsin. ancak bir etiket gerektiren goto'nun aksine nereye gidileceğini bilir. Sonra, kontrolü bir sonraki ara katman fonksiyonuna geçirir. Ayrıca, istediğinizi 'sonraki' olarak adlandırabilirsiniz. Burada sadece bir etiket var. Ancak en iyi uygulama 'next' adını kullanmaktır
Mav55

3
Tamam, bu doğru değil gibi görünüyor. Ben kodu denedim ( burada pastebin ) ve next()çağrıdan sonra kod çağrılır . Bu durumda, past the next() callkonsola yazılır ve başarısız olsa Error: Can't set headers after they are sent.da ikincisi res.sendçağrıldığında bir hata alıyorum . Kod akışı çağrıdan sonra geri dönernext() , bu da @ Ashe'nin returns(veya diğer mantık yönetiminin) önemli olmasını sağlar.
ruffin

4
@ruffin, evet haklısın. next()Kalan ifadelerin yürütülmesini atlamak için bir iade ifadesine ihtiyacımız var . işaret ettiğin için teşekkürler.
Mav55

1
Aslında "ara katman yazılımı" nın ne olduğunu açıkladığınız için teşekkür ederiz. Aslında ne olduğu, neden ve nasıl olduğu hakkında net bir şey söyleyen tek cevap buydu.
mc01


5

Bu işlevi çağırmak, uygulamadaki bir sonraki ara katman yazılımı işlevini çağırır. Next () işlevi, Node.js veya Express API'sinin bir parçası değil, orta katman işlevine iletilen üçüncü bağımsız değişkendir. Next () işlevi herhangi bir şey olarak adlandırılabilir, ancak kural olarak her zaman “next” olarak adlandırılır.


2

nextİşlevin yürütülmesi, sunucuya bu ara katman yazılımı adımıyla tamamlandığınızı bildirir ve zincirde bir sonraki adımı yürütebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.