Ekspresikan fungsi selanjutnya, untuk apa sebenarnya ini?

124

Telah mencoba menemukan deskripsi yang baik tentang apa yang dilakukan next()metode tersebut. Dalam dokumentasi Express disebutkan bahwa next('route')dapat digunakan untuk melompat ke rute itu dan melewati semua rute di antaranya, tetapi terkadang nextdipanggil tanpa argumen. Ada yang tahu tutorial bagus dll yang menjelaskan nextfungsinya?

Andreas Selenwall
sumber

Jawaban:

161

next()tanpa argumen mengatakan "hanya bercanda, saya sebenarnya tidak ingin menangani ini". Ia kembali dan mencoba untuk menemukan rute berikutnya yang cocok.

Ini berguna, katakanlah jika Anda ingin memiliki semacam pengelola halaman dengan siput url, serta banyak hal lainnya, tetapi berikut adalah contohnya.

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() {
  //...
});

Kode yang dibuat harus memeriksa database untuk halaman dengan siput id tertentu. Jika ditemukan, berikanlah! jika tidak menemukannya, abaikan penangan rute ini dan periksa yang lain.

Jadi next()tanpa argumen memungkinkan untuk berpura-pura Anda tidak menangani rute sehingga sesuatu yang lain dapat mengambilnya sebagai gantinya.


Atau serangan balasan dengan app.all('*'). Yang memungkinkan Anda untuk menjalankan beberapa kode penyiapan bersama dan kemudian beralih ke rute lain untuk melakukan sesuatu yang lebih spesifik.

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

app.get('/other_routes', function() {
  //...
});
Alex Wayne
sumber
Jawaban yang bagus! Saya telah melihat beberapa penggunaan lain dari next juga, misalnya next (err) dan next ('route'). Apakah Anda sekarang tujuan dari ini, kapan Anda ingin menyebarkan kesalahan, dan kapan Anda ingin melompat ke rute tertentu?
Andreas Selenwall
8
@AndreasSelenwall next('route')khusus untuk app.VERB()dan digunakan ketika rute memiliki beberapa callback untuk " melewati callback rute yang tersisa. " next(err)Digunakan untuk melompat ke " error middleware " ( Edari posting).
Jonathan Lonowski
5
Suara positif. Hanya untuk kalimat ini: "hanya bercanda, saya sebenarnya tidak ingin menangani ini" Anda membuat saya mengerti apa yang saya cari. Saya melihat banyak pertanyaan serupa, dan menemukan solusi dalam satu kalimat.
Pedro Barros
8
Memanggil next()tanpa argumen tidak benar-benar memberi tahu sistem "saya tidak ingin menangani ini", ini hanya memberi tahu sistem untuk terus memproses setiap middlewares yang tersisa setelah ini selesai. Ini bukan kondisi kesalahan untuk menelepon next(), itu bagian dari aliran normal. Jika Anda tidak menelepon, next()tidak ada rute lain yang akan diproses sama sekali.
d512
1
Saya berharap lebih banyak jawaban di situs web ini ditulis untuk orang awam ... 'next () tanpa argumen mengatakan "hanya bercanda, saya sebenarnya tidak ingin menangani ini"' - Sempurna untuk noobs ... (@ d512 memiliki penjelasan yang lebih baik)
daCoda
129

Di sebagian besar kerangka kerja, Anda mendapatkan permintaan dan Anda ingin membalas. Karena sifat asinkron Node.js, Anda mengalami masalah dengan panggilan balik bersarang jika Anda melakukan hal-hal yang tidak sepele. Untuk mencegah hal ini terjadi, Connect.js (sebelum v4.0, Express.js adalah lapisan di atas connect.js) memiliki sesuatu yang disebut middleware yang merupakan fungsi dengan 2, 3 atau 4 parameter.

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

Aplikasi Express.js Anda adalah kumpulan dari fungsi-fungsi ini.

masukkan deskripsi gambar di sini

Router itu spesial, ini middleware yang memungkinkan Anda mengeksekusi satu atau lebih middleware untuk url tertentu. Jadi tumpukan di dalam tumpukan.

Jadi apa yang selanjutnya dilakukan? Sederhana, ini memberi tahu aplikasi Anda untuk menjalankan middleware berikutnya. Tetapi apa yang terjadi ketika Anda meneruskan sesuatu ke berikutnya? Express akan membatalkan stack saat ini dan menjalankan semua middleware yang memiliki 4 parameter.

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

Middleware ini digunakan untuk memproses kesalahan apa pun. Saya suka melakukan hal berikut:

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

Dengan kesalahan ini saya mungkin akan memberi tahu pengguna ada yang tidak beres dan mencatat kesalahan sebenarnya.

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

Jika Anda membayangkan aplikasi Express.js Anda sebagai tumpukan, Anda mungkin bisa memperbaiki sendiri banyak keanehan. Misalnya ketika Anda menambahkan middleware Cookie setelah Anda merute, masuk akal bahwa rute Anda tidak memiliki cookie.

Pickel
sumber
3
Di mana Anda akan menyimpan fungsi pencatatan anonim ini?
dennismonsewicz
"Express akan membatalkan stack saat ini dan menjalankan semua middleware yang memiliki 4 parameter." Saya bertanya-tanya bagaimana express dapat menjalankan middlewares penanganan kesalahan yang tepat. Terima kasih!
Abhishek Agarwal
75

IMHO, jawaban yang diterima untuk pertanyaan ini tidak terlalu akurat. Seperti yang dinyatakan orang lain, ini benar-benar tentang mengontrol kapan penangan berikutnya dalam rantai dijalankan. Tetapi saya ingin memberikan sedikit lebih banyak kode untuk membuatnya lebih konkret. Katakanlah Anda memiliki aplikasi ekspres sederhana ini:

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!')
});

Jika kamu melakukan

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

Anda akan melihat ini dicetak ke konsol:

before request handler
handling request
after request handler

Sekarang jika Anda mengomentari panggilan ke next()penangan tengah seperti ini:

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

Anda akan melihat ini di konsol:

before request handler
handling request

Perhatikan bahwa penangan terakhir (yang mencetak after request handler) tidak berjalan. Itu karena Anda tidak lagi memberi tahu ekspres untuk menjalankan penangan berikutnya.

Jadi tidak masalah apakah penangan "utama" Anda (yang mengembalikan 200) berhasil atau tidak, jika Anda ingin agar perantara lainnya berjalan, Anda harus memanggil next().

Kapan ini akan berguna? Katakanlah Anda ingin mencatat semua permintaan yang masuk ke beberapa database terlepas dari apakah permintaan itu berhasil atau tidak.

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();
});

Jika Anda ingin penangan kedua berjalan, Anda harus memanggil next()penangan pertama.

Ingatlah bahwa node itu asinkron sehingga tidak dapat mengetahui kapan callback penangan pertama telah selesai. Anda harus mengatakannya dengan menelepon next().

d512
sumber
Sonfar jawaban terbaik buat saya.
Norayr Ghukasyan
Nah penjelasannya!
Chang
7

next () tanpa parameter memanggil penangan rute berikutnya ATAU middleware berikutnya dalam kerangka kerja.

kyasar.dll
sumber
2
Atau middleware berikutnya.
robertklep
1

Ini berarti memberikan kontrol ke pawang berikutnya.

Bersulang

Nyai
sumber
1

Perhatikan panggilan di atas ke next (). Memanggil fungsi ini akan memanggil fungsi middleware berikutnya dalam aplikasi. Fungsi next () bukan bagian dari Node.js atau Express API, tetapi merupakan argumen ketiga yang diteruskan ke fungsi middleware. Fungsi next () bisa dinamai apa saja, tetapi menurut konvensi, itu selalu dinamai "next". Untuk menghindari kebingungan, selalu gunakan konvensi ini.

Hukmaram
sumber
0

Pertanyaan juga ditanyakan tentang penggunaan next ('rute') yang tampaknya dibahas minggu dalam jawaban yang diberikan sejauh ini:

  1. PENGGUNAAN next ():

Singkatnya: fungsi middleware berikutnya.

Ekstrak dari dokumentasi Express JS resmi ini - halaman 'writing-middleware' :

"Fungsi middleware myLogger hanya mencetak pesan, lalu meneruskan permintaan tersebut ke fungsi middleware berikutnya dalam stack dengan memanggil fungsi next ()."

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)

Halaman dokumentasi Express JS ini menyatakan "Jika fungsi middleware saat ini tidak mengakhiri siklus permintaan-respons, ia harus memanggil next () untuk meneruskan kontrol ke fungsi middleware berikutnya. Jika tidak, permintaan akan dibiarkan menggantung."

  1. PENGGUNAAN berikutnya ('rute'):

Singkatnya: rute berikutnya (vs. fungsi middleware berikutnya dalam kasus next ())

Ekstrak dari dokumentasi Express JS ini - halaman 'using-middleware' :

"Untuk melewati fungsi middleware lainnya dari tumpukan middleware router, panggil next ('route') untuk meneruskan kontrol ke rute berikutnya . CATATAN: next ('route') hanya akan berfungsi di fungsi middleware yang dimuat dengan menggunakan app.METHOD () atau router.METHOD ().

Contoh ini menunjukkan sub-stack middleware yang menangani permintaan GET ke jalur / user /: id. "

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')
})
Ula
sumber
0

next () adalah argumen callback ke fungsi middleware dengan req, dan res menjadi argumen permintaan dan respons http ke next dalam kode di bawah ini.

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

Jadi next () memanggil fungsi middleware yang diteruskan. Jika fungsi middleware saat ini tidak mengakhiri siklus permintaan-respons, ia harus memanggil next (), jika tidak, permintaan akan dibiarkan hang dan akan habis waktu.

next () fn perlu dipanggil dalam setiap fungsi middleware ketika beberapa fungsi middleware diteruskan ke app.use atau app.METHOD, jika tidak, fungsi middleware berikutnya tidak akan dipanggil (jika lebih dari 1 fungsi middleware diteruskan). Untuk melewati pemanggilan fungsi middleware yang tersisa, panggil next ('route') dalam fungsi middleware yang setelah itu tidak ada fungsi middleware lain yang harus dipanggil. Pada kode di bawah ini, fn1 akan dipanggil dan fn2 juga akan dipanggil, karena next () dipanggil dalam fn1. Namun, fn3 tidak akan dipanggil, karena next ('route') dipanggil dalam fn2.

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();
})
pengguna3022150
sumber