Bir sonraki işlevi ifade edin, gerçekten ne için?


124

next()Yöntemin ne işe yaradığına dair iyi bir açıklama bulmaya çalışıyorum . Ekspres belgelerde next('route'), o rotaya atlamak ve aradaki tüm rotaları atlamak için kullanılabileceğini söylüyor , ancak bazen nextbağımsız değişkenler olmadan çağrılıyor. nextİşlevi açıklayan iyi bir öğretici vb. Bilen var mı?

Yanıtlar:


161

next()hiçbir argüman olmadan "sadece şaka yapıyorum, bunu gerçekten halletmek istemiyorum" diyor. Geri döner ve eşleşen bir sonraki rotayı bulmaya çalışır.

Bu yararlıdır, mesela url sümüklü böcekleri olan bir tür sayfa yöneticisine ve diğer birçok şeye sahip olmak istiyorsanız, ama işte bir örnek.

app.get('/:pageslug', function(req, res, next){
  var page = db.findPage(req.params.pageslug);
  if (page) {
    res.send(page.body);
  } else {
    next();
  }
});

app.get('/other_routes', function() {
  //...
});

Oluşturulan kod, belirli bir kimlik bilgisine sahip bir sayfa için bir veritabanını kontrol etmelidir. Bir tane bulursa onu render! birini bulamazsa, bu rota işleyicisini yok sayın ve diğerlerini kontrol edin.

Yani next()hiçbir argüman olmadan rotayı kontrol etmemişsiniz gibi davranmanıza izin verir, böylece başka bir şey onu alabilir.


Veya bir hit counter ile app.all('*'). Bu, bazı paylaşılan kurulum kodunu çalıştırmanıza ve ardından daha spesifik bir şey yapmak için diğer yollara geçmenize izin verir.

app.all('*', function(req, res, next){
  myHitCounter.count += 1;
  next();
});

app.get('/other_routes', function() {
  //...
});

Mükemmel cevap! Next (sonraki) ve sonraki ('rota') gibi başka bir kullanım da gördüm. Şimdi bunların amacı siz misiniz, bir hatayı ne zaman yaymak istersiniz ve belirli bir rotaya ne zaman atlamak istersiniz?
Andreas Selenwall

8
@AndreasSelenwall next('route')özeldir app.VERB()ve bir yol "birden fazla geri aramalar sahip olduğunda kullanılır kalan yol geri arama (lar). Baypas " next(err)bir "atlamak için kullanılan hata katman (" Eyazısı).
Jonathan Lonowski

5
Upvoted. Sırf şu söz için: "Şaka yapıyorum, bunu gerçekten halletmek istemiyorum" ne aradığımı anlamamı sağladın. Bir çok benzer soru gördüm ve tek bir cümleyle çözüm buldum.
Pedro Barros

8
next()Hiçbir argüman olmadan çağrı yapmak sisteme "bunu halletmek istemiyorum" demez, sadece sisteme bu işlem tamamlandıktan sonra kalan ara yazılımları işlemeye devam etmesini söyler. Çağrılması gereken bir hata koşulu değil next(), normal akışın bir parçası. Eğer aramazsan next()başka yolları hiç işlenecektir.
d512

1
Keşke bu web sitesinde meslekten olmayanlar için daha fazla cevap yazılsaydı ... 'next () hiçbir argüman olmadan "sadece şaka yapıyorum, bunu gerçekten halletmek istemiyorum" diyor - Çaylaklar için mükemmel ... (@ d512'de daha iyi bir açıklama olsa da)
daCoda

129

Çoğu çerçevede bir istek alırsınız ve bir yanıt döndürmek istersiniz. Node.js'nin eşzamansız doğası nedeniyle, önemsiz olmayan şeyler yapıyorsanız, iç içe geçmiş geri aramalarla sorun yaşarsınız. Bunun olmasını önlemek için Connect.js (v4.0'dan önce, Express.js, connect.js'nin üstünde bir katmandı), 2, 3 veya 4 parametreli bir işlev olan ara yazılım adı verilen bir şeye sahiptir.

function (<err>, req, res, next) {}

Express.js uygulamanız bu işlevlerin bir yığınından oluşur.

görüntü açıklamasını buraya girin

Yönlendirici özeldir, belirli bir url için bir veya daha fazla ara yazılım çalıştırmanıza izin veren bir ara yazılımdır. Yani bir yığının içindeki yığın.

Peki şimdi ne yapacak? Basittir, uygulamanıza bir sonraki ara yazılımı çalıştırmasını söyler. Ama bir sonraki adıma geçtiğinizde ne olur? Express, mevcut yığını iptal edecek ve 4 parametreye sahip tüm ara yazılımı çalıştıracaktır.

function (err, req, res, next) {}

Bu ara yazılım, herhangi bir hatayı işlemek için kullanılır. Aşağıdakileri yapmaktan hoşlanıyorum:

next({ type: 'database', error: 'datacenter blew up' });

Bu hatayla, muhtemelen kullanıcıya bir şeylerin ters gittiğini söyler ve gerçek hatayı günlüğe kaydederdim.

function (err, req, res, next) {
   if (err.type === 'database') {
     res.send('Something went wrong user');
     console.log(err.error);
   }
};

Express.js uygulamanızı bir yığın olarak resmederseniz, muhtemelen birçok tuhaflığı kendiniz giderebilirsiniz. Örneğin, yönlendiricinizden sonra Çerez ara yazılımınızı eklediğinizde, rotalarınızın çerez içermeyeceği anlamlıdır.


3
Bu anonim günlük kaydı işlevini nerede saklarsınız?
dennismonsewicz

"Express, mevcut yığını iptal edecek ve 4 parametreye sahip tüm ara yazılımı çalıştıracaktır." Express'in tam hata işleyici araç yazılımlarını nasıl çalıştırdığını merak ediyordum. Teşekkürler!
Abhishek Agarwal

75

IMHO, bu sorunun kabul edilen cevabı gerçekten doğru değil. Diğerlerinin de belirttiği gibi, bu gerçekten zincirdeki bir sonraki işleyicinin ne zaman çalıştırılacağını kontrol etmekle ilgilidir. Ama daha somut hale getirmek için biraz daha kod sağlamak istedim. Bu basit ekspres uygulamaya sahip olduğunuzu varsayalım:

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

app.get('/user/:id', function (req, res, next) {
    console.log('before request handler');
    next();
});

app.get('/user/:id', function (req, res, next) {
    console.log('handling request');
    res.sendStatus(200);
    next();
});

app.get('/user/:id', function (req, res, next) {
    console.log('after request handler');
    next();
});

app.listen(3000, function () {
    console.log('Example app listening on port 3000!')
});

Yaparsan

curl http://localhost:3000/user/123

bunun konsola yazdırıldığını göreceksiniz:

before request handler
handling request
after request handler

Şimdi next(), orta işleyicideki çağrıyı şöyle yorumlarsanız:

app.get('/user/:id', function (req, res, next) {
    console.log('handling request');
    res.sendStatus(200);
    //next();
});

Bunu konsolda göreceksiniz:

before request handler
handling request

Son işleyicinin (yazdıran after request handler) çalışmadığına dikkat edin. Bunun nedeni, artık bir sonraki işleyiciyi çalıştırmanızı ifade etmiyorsunuzdur.

Bu nedenle, "ana" işleyicinizin (200 döndüren) başarılı olup olmaması gerçekten önemli değil, ara yazılımların geri kalanının çalışmasını istiyorsanız, aramanız gerekir next().

Bu ne zaman işe yarayacak? Diyelim ki, istek başarılı olsun ya da olmasın, bazı veritabanlarına gelen tüm istekleri günlüğe kaydetmek istediğinizi varsayalım.

app.get('/user/:id', function (req, res, next) {
    try {
       // ...
    }
    catch (ex) {
       // ...
    }
    finally {
       // go to the next handler regardless of what happened in this one
       next();
    }
});

app.get('/user/:id', function (req, res, next) {
    logToDatabase(req);
    next();
});

İkinci işleyicinin çalışmasını istiyorsanız next(), ilk işleyiciyi aramanız gerekir .

Düğümün eşzamansız olduğunu unutmayın, böylece ilk işleyicinin geri aramasının ne zaman bittiğini bilemez. Bunu arayarak söylemelisin next().


Sonfar benim için en iyi cevap.
Norayr Ghukasyan

İyi açıklama!
Chang

7

next () parametresiz bir sonraki yol işleyicisini VEYA çerçevedeki sonraki ara yazılımı çağırır.


2
Veya bir sonraki ara katman yazılımı.
robertklep

1

Basitçe, kontrolü bir sonraki işleyiciye geçirmek anlamına gelir.

Şerefe


1

Yukarıdaki çağrıya dikkat edin sonraki (). Bu işlevi çağırmak, uygulamadaki bir sonraki ara yazılım işlevini çağırır. Next () işlevi, Node.js veya Express API'nin bir parçası değildir, ancak ara yazılım işlevine iletilen üçüncü bağımsız değişkendir. Next () işlevi herhangi bir şekilde adlandırılabilir, ancak geleneksel olarak her zaman "sonraki" olarak adlandırılır. Karışıklığı önlemek için her zaman bu kuralı kullanın.


0

Şu ana kadar verilen cevaplarda hafta içinde kapsanacak gibi görünen sonraki ('yol') kullanımı hakkında soru da soruldu:

  1. Sonraki () KULLANIMI:

Kısaca: bir sonraki ara katman işlevi.

Bu resmi Express JS belgelerinden - 'yazma-ara yazılım' sayfasından alın :

"Ara yazılım işlevi myLogger basitçe bir mesaj yazdırır, ardından next () işlevini çağırarak isteği yığındaki bir sonraki ara katman işlevine aktarır ."

var express = require('express')
var app = express()

var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

app.use(myLogger)

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

app.listen(3000)

Express JS dokümantasyonunun bu sayfasında "Mevcut ara yazılım işlevi istek-yanıt döngüsünü sonlandırmazsa, denetimi bir sonraki ara yazılım işlevine geçirmek için next () 'yi çağırmalıdır. Aksi takdirde istek asılı kalır."

  1. Sonraki ('rota') KULLANIMI:

Kısaca: sonraki rota ( sonraki ara yazılım işlevine karşı ())

Bu Express JS belgelerinden - 'ara yazılım kullanma' sayfasından çıkarın :

"Bir yönlendirici ara yazılım yığınındaki ara yazılım işlevlerinin geri kalanını atlamak için, kontrolü bir sonraki yola geçirmek için bir sonraki ('yol') öğesini çağırın . NOT: sonraki ('yol') yalnızca, app.METHOD () veya router.METHOD () işlevleri.

Bu örnek, / user /: id yoluna GET isteklerini işleyen bir ara yazılım alt yığınını gösterir. "

app.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next route
  if (req.params.id === '0') next('route')
  // otherwise pass the control to the next middleware function in this stack
  else next()
}, function (req, res, next) {
  // render a regular page
  res.render('regular')
})

// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
  res.render('special')
})

0

next () , req ile ara yazılım işlevinin geri arama bağımsız değişkenidir ve res, aşağıdaki kodda sonraki http isteği ve yanıt bağımsız değişkenleridir.

app.get ('/', (req, res, sonraki) => {next ()});

Bu yüzden next () geçilen ara yazılım işlevini çağırır. Mevcut ara yazılım işlevi istek-yanıt döngüsünü sonlandırmazsa, next () öğesini çağırmalıdır, aksi takdirde istek asılı kalır ve zaman aşımına uğrar.

app.use veya app.METHOD'a birden çok ara yazılım işlevi geçirildiğinde, her bir ara yazılım işlevi içinde next () fn çağrılması gerekir, aksi takdirde sonraki ara yazılım işlevi çağrılmaz (1'den fazla ara yazılım işlevi geçirilirse). Kalan ara yazılım işlevlerini çağırmayı atlamak için , ara yazılım işlevi içinde bir sonraki ('yol') öğesini çağırın ; bundan sonra başka ara yazılım işlevleri çağrılmamalıdır. Aşağıdaki kodda, fn1 çağrılacak ve fn2 de çağrılacaktır, çünkü next () fn1 içinde çağrılır. Ancak, sonraki ('rota') fn2 içinde çağrıldığından fn3 çağrılmaz.

app.get('/fetch', function fn1(req, res, next)  {
console.log("First middleware function called"); 
    next();
}, 
function fn2(req, res, next) {
    console.log("Second middleware function called"); 
    next("route");
}, 
function fn3(req, res, next) {
    console.log("Third middleware function will not be called"); 
    next();
})
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.