Chức năng tiếp theo Express, nó thực sự để làm gì?


124

Đã cố gắng tìm ra một mô tả tốt về những gì next()phương pháp này thực hiện. Trong tài liệu Express, nó nói rằng next('route')có thể được sử dụng để chuyển đến tuyến đường đó và bỏ qua tất cả các tuyến đường ở giữa, nhưng đôi khi nextđược gọi mà không có đối số. Có ai biết về một hướng dẫn tốt, v.v. mô tả nextchức năng không?

Câu trả lời:


161

next()không có đối số nói rằng "chỉ đùa thôi, tôi thực sự không muốn xử lý việc này". Nó quay trở lại và cố gắng tìm tuyến đường tiếp theo phù hợp.

Điều này rất hữu ích, giả sử nếu bạn muốn có một số loại trình quản lý trang với url slugs, cũng như nhiều thứ khác, nhưng đây là một ví dụ.

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

Mã được tạo thành đó sẽ kiểm tra cơ sở dữ liệu cho một trang có slug id nhất định. Nếu nó tìm thấy một kết xuất nó! nếu nó không tìm thấy thì hãy bỏ qua trình xử lý tuyến đường này và kiểm tra những cái khác.

Vì vậy, next()không có đối số nào cho phép giả vờ bạn không xử lý tuyến đường để thứ khác có thể lấy nó thay thế.


Hoặc một bộ đếm hit với app.all('*'). Điều này cho phép bạn thực thi một số mã thiết lập được chia sẻ và sau đó chuyển sang các tuyến đường khác để làm điều gì đó cụ thể hơn.

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

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

Câu trả lời chính xác! Tôi đã thấy một số cách sử dụng khác của next cũng như next (err) và next ('route'). Bây giờ bạn có mục đích của những điều này không, khi nào bạn muốn tuyên truyền một lỗi và khi nào bạn muốn chuyển sang một tuyến đường nhất định?
Andreas Selenwall,

8
@AndreasSelenwall next('route')dành riêng cho app.VERB()và được sử dụng khi một tuyến có nhiều lệnh gọi lại để " bỏ qua (các) cuộc gọi lại của tuyến đường còn lại. " next(err)Được sử dụng để chuyển đến bất kỳ " phần mềm trung gian lỗi " nào ( Etừ bài đăng).
Jonathan Lonowski 30/10/12

5
Đã ủng hộ. Chỉ với cụm từ này: "đùa thôi, tôi thực sự không muốn xử lý việc này" bạn đã khiến tôi hiểu những gì tôi đang tìm kiếm. Tôi đã thấy rất nhiều câu hỏi tương tự và tìm thấy giải pháp trong một cụm từ.
Pedro Barros

8
Việc gọi next()mà không có đối số không thực sự nói với hệ thống "tôi không muốn xử lý việc này", nó chỉ cho hệ thống tiếp tục xử lý bất kỳ phần mềm trung gian nào còn lại sau khi quá trình này được thực hiện. Nó không phải là một điều kiện lỗi để gọi next(), nó là một phần của quy trình bình thường. Nếu bạn không gọi, sẽ next()không có các tuyến đường khác được xử lý.
d512

1
Tôi ước có nhiều câu trả lời hơn trên trang web này được viết cho giáo dân ... 'next () mà không có đối số nói rằng "chỉ đùa thôi, tôi không thực sự muốn xử lý việc này"' - Perfect for noobs ... (@ d512 has a giải thích tốt hơn mặc dù)
daCoda

129

Trong hầu hết các khuôn khổ, bạn nhận được một yêu cầu và bạn muốn trả lại phản hồi. Do tính chất không đồng bộ của Node.js, bạn sẽ gặp phải sự cố với các cuộc gọi ngược lồng nhau nếu bạn đang làm những việc không tầm thường. Để ngăn điều này xảy ra Connect.js (trước v4.0, Express.js là một lớp trên đầu của connect.js) có một thứ gọi là phần mềm trung gian, là một hàm có 2, 3 hoặc 4 tham số.

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

Ứng dụng Express.js của bạn là một tập hợp các chức năng này.

nhập mô tả hình ảnh ở đây

Bộ định tuyến rất đặc biệt, nó là phần mềm trung gian cho phép bạn thực thi một hoặc nhiều phần mềm trung gian cho một url nhất định. Vì vậy, nó là một ngăn xếp bên trong một ngăn xếp.

Vậy tiếp theo phải làm gì? Đơn giản, nó yêu cầu ứng dụng của bạn chạy phần mềm trung gian tiếp theo. Nhưng điều gì sẽ xảy ra khi bạn chuyển thứ gì đó sang thứ tiếp theo? Express sẽ hủy bỏ ngăn xếp hiện tại và sẽ chạy tất cả phần mềm trung gian có 4 tham số.

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

Phần mềm trung gian này được sử dụng để xử lý bất kỳ lỗi nào. Tôi thích làm như sau:

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

Với lỗi này, tôi có thể sẽ cho người dùng biết có gì đó không ổn và ghi lại lỗi thực sự.

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

Nếu bạn hình dung ứng dụng Express.js của mình như một ngăn xếp, bạn có thể sẽ tự khắc phục được rất nhiều điều kỳ lạ. Ví dụ: khi bạn thêm phần mềm trung gian Cookie của mình sau khi bạn định tuyến, điều đó có nghĩa là các tuyến đường của bạn sẽ không có cookie.


3
Bạn sẽ lưu trữ chức năng ghi nhật ký ẩn danh này ở đâu?
dennismonsewicz

"Express sẽ hủy bỏ ngăn xếp hiện tại và sẽ chạy tất cả phần mềm trung gian có 4 tham số." tôi đã tự hỏi làm thế nào express có thể chạy phần mềm trung gian xử lý lỗi chính xác. Cảm ơn!
Abhishek Agarwal

75

IMHO, câu trả lời được chấp nhận cho câu hỏi này không thực sự chính xác. Như những người khác đã nói, nó thực sự là về việc kiểm soát khi nào trình xử lý tiếp theo trong chuỗi được chạy. Nhưng tôi muốn cung cấp thêm một chút mã để làm cho nó cụ thể hơn. Giả sử bạn có ứng dụng nhanh đơn giản này:

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

Nếu bạn làm

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

bạn sẽ thấy điều này được in ra bảng điều khiển:

before request handler
handling request
after request handler

Bây giờ nếu bạn nhận xét cuộc gọi đến next()trong trình xử lý giữa như thế này:

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

Bạn sẽ thấy điều này trên bảng điều khiển:

before request handler
handling request

Lưu ý rằng trình xử lý cuối cùng (trình xử lý được in ra after request handler) không chạy. Đó là bởi vì bạn không còn yêu cầu express chạy trình xử lý tiếp theo.

Vì vậy, không thực sự quan trọng nếu trình xử lý "chính" của bạn (trình xử lý trả về 200) thành công hay không, nếu bạn muốn phần mềm trung gian còn lại chạy, bạn phải gọi next().

Khi nào điều này sẽ có ích? Giả sử bạn muốn ghi lại tất cả các yêu cầu đến cơ sở dữ liệu nào đó bất kể yêu cầu đó có thành công hay không.

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

Nếu bạn muốn trình xử lý thứ hai chạy, bạn phải gọi next()trong trình xử lý thứ nhất.

Hãy nhớ rằng nút không đồng bộ nên nó không thể biết khi nào lệnh gọi lại của trình xử lý đầu tiên kết thúc. Bạn phải nói với nó bằng cách gọi điện next().


Sonfar câu trả lời tốt nhất cho tôi.
Norayr Ghukasyan

Giải thích tốt!
Chang

7

next () không có tham số gọi trình xử lý tuyến tiếp theo HOẶC phần mềm trung gian tiếp theo trong khuôn khổ.


2
Hoặc phần mềm trung gian tiếp theo.
robertklep


1

Lưu ý cuộc gọi ở trên tới next (). Việc gọi hàm này sẽ gọi hàm phần mềm trung gian tiếp theo trong ứng dụng. Hàm next () không phải là một phần của Node.js hoặc Express API, nhưng là đối số thứ ba được chuyển cho hàm middleware. Hàm next () có thể được đặt tên bất kỳ thứ gì, nhưng theo quy ước, nó luôn được đặt tên là “next”. Để tránh nhầm lẫn, hãy luôn sử dụng quy ước này.


0

Câu hỏi cũng được hỏi về việc sử dụng tiếp theo ('tuyến đường') dường như đã được đề cập trong tuần trong các câu trả lời được cung cấp cho đến nay:

  1. CÁCH SỬ DỤNG next ():

Trong ngắn hạn: chức năng phần mềm trung gian tiếp theo.

Trích xuất từ tài liệu Express JS chính thức này - trang 'write-middleware' :

"Hàm phần mềm trung gian myLogger chỉ cần in một thông báo, sau đó chuyển yêu cầu đến hàm phần mềm trung gian tiếp theo trong ngăn xếp bằng cách gọi hàm 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)

Trang tài liệu Express JS này nêu rõ "Nếu chức năng phần mềm trung gian hiện tại không kết thúc chu kỳ yêu cầu-phản hồi, nó phải gọi next () để chuyển quyền kiểm soát cho chức năng phần mềm trung gian tiếp theo. Nếu không, yêu cầu sẽ bị treo."

  1. SỬ DỤNG CỦA TIẾP THEO ('route'):

Tóm lại: tuyến đường tiếp theo (so với hàm phần mềm trung gian tiếp theo trong trường hợp tiếp theo ())

Trích xuất từ tài liệu Express JS này - trang 'using-middleware' :

"Để bỏ qua phần còn lại của các chức năng phần mềm trung gian khỏi ngăn xếp phần mềm trung gian của bộ định tuyến, hãy gọi next ('route') để chuyển quyền kiểm soát cho đường tiếp theo . LƯU Ý: next ('route') sẽ chỉ hoạt động trong các chức năng phần mềm trung gian được tải bằng cách sử dụng các hàm app.METHOD () hoặc router.METHOD ().

Ví dụ này cho thấy một ngăn xếp con phần mềm trung gian xử lý các yêu cầu GET đến đường dẫn / 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')
})

0

next () là đối số gọi lại hàm middleware với req và res là đối số yêu cầu và phản hồi http đối với tiếp theo trong đoạn mã dưới đây.

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

Vì vậy, next () gọi hàm được truyền trong phần mềm trung gian. Nếu chức năng phần mềm trung gian hiện tại không kết thúc chu kỳ yêu cầu-phản hồi, nó sẽ gọi next (), nếu không yêu cầu sẽ bị treo và sẽ hết thời gian chờ.

next () fn cần được gọi trong mỗi chức năng phần mềm trung gian khi nhiều chức năng phần mềm trung gian được chuyển đến app.use hoặc app.METHOD, nếu không thì chức năng phần mềm trung gian tiếp theo sẽ không được gọi (trong trường hợp nhiều hơn 1 chức năng phần mềm trung gian được chuyển). Để bỏ qua việc gọi các chức năng phần mềm trung gian còn lại, hãy gọi tiếp theo ('route') trong chức năng phần mềm trung gian mà sau đó không được gọi các chức năng phần mềm trung gian khác. Trong đoạn mã dưới đây, fn1 sẽ được gọi và fn2 cũng sẽ được gọi, vì next () được gọi trong fn1. Tuy nhiên, fn3 sẽ không được gọi, vì next ('route') được gọi trong 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();
})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.