Висловіть наступну функцію, для чого це насправді?


124

Намагалися знайти хороший опис того, що next()робить метод. У документації «Експрес» зазначено, що next('route')можна використовувати для переходу до цього маршруту та пропускання між ними всіх маршрутів, але іноді nextвикликається без аргументів. Хтось знає про хороший підручник тощо, який описує nextфункцію?

Відповіді:


161

next()без жодних аргументів говорить "просто жартую, я фактично не хочу з цим впоратися". Він повертається назад і намагається знайти наступний маршрут, який би відповідав.

Це корисно, скажімо, якщо ви хочете мати якийсь диспетчер сторінок з URL-адресами, а також багато інших речей, але ось приклад.

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

Створений код повинен перевірити базу даних на сторінку з певним слупою id. Якщо він знайде одного візуалізувати! якщо він не знайде його, ігноруйте цей обробник маршруту та перевірте інші.

Тож next()без жодних аргументів можна робити вигляд, що ви не впоралися з маршрутом, так що щось інше може вибрати його замість нього.


Або лічильник ударів с app.all('*'). Це дозволяє виконати деякий загальний код налаштування, а потім перейти на інші маршрути, щоб зробити щось більш конкретне.

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

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

Чудова відповідь! Я бачив і інше використання next, наприклад next (помилка) та next ('route'). Чи є тепер у вас мета цих, коли ви хочете поширити помилку, і коли ви хочете перейти на певний маршрут?
Андреас Селенволл

8
@AndreasSelenwall next('route')є специфічним для app.VERB()і використовується , коли маршрут має кілька зворотних викликів до « обхідного залишився маршруту зворотного виклику (и). » next(err)Використовується для переходу до якої - небудь « помилок проміжного програмного забезпечення » ( Eвід посади).
Джонатан Лоновський

5
Отримано. Просто за цією фразою: "просто жартую, я фактично не хочу впоратися з цим", ти дав мені зрозуміти, що я шукав. Я побачив багато подібних питань і знайшов рішення в одній фразі.
Педро Баррос

8
Виклик next()без аргументів насправді не вказує системі "я не хочу з цим впоратися", вона просто повідомляє системі продовжувати обробку будь-яких інших проміжних програм після того, як це буде зроблено. Це не умова помилки для виклику next(), це частина нормального потоку. Якщо ви не телефонуєте, next()інші маршрути взагалі не будуть оброблені.
d512

1
Я хотів би, щоб більше відповідей на цьому веб-сайті було написано для мирян ... 'Наступний () без аргументів говорить "просто жартую, я фактично не хочу впоратися з цим" "- Ідеально підходить для нобусів ... (@ d512 має краще пояснення, хоча)
daCoda

129

У більшості рамок ви отримуєте запит і хочете повернути відповідь. Через асинхронний характер Node.js у вас виникають проблеми з вкладеними зворотними дзвінками, якщо ви робите нетривіальні речі. Щоб цього не сталося, Connect.js (до версії v4.0, Express.js був шаром зверху connect.js) має щось, що називається середнім програмним забезпеченням, яке є функцією з 2, 3 або 4 параметрами.

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

Ваш додаток Express.js - це ціла група цих функцій.

введіть тут опис зображення

Роутер є спеціальним, саме середнє програмне забезпечення дозволяє виконувати одне або кілька проміжних програм для певної URL-адреси. Отже, це стек всередині стопки.

Отже, що робити далі? Просто, він говорить вашому додатку запустити наступне програмне забезпечення. Але що відбувається, коли ти передаєш щось наступному? Express скасує поточний стек і запустить усе проміжне програмне забезпечення, яке має 4 параметри.

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

Ця проміжна програма використовується для обробки будь-яких помилок. Мені подобається робити наступне:

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

З цією помилкою я, мабуть, скажу користувачеві, що щось пішло не так і зафіксував справжню помилку.

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

Якщо ви представляєте додаток Express.js як стек, ви, ймовірно, зможете самостійно виправити багато дивацтва. Наприклад, коли ви додаєте проміжне програмне забезпечення Cookie після маршрутизатора, має сенс, що у ваших маршрутах не буде файлів cookie.


3
Де б ви зберігали цю функцію анонімного ведення журналу?
dennismonsewicz

"Експрес скасує поточний стек і запустить усе проміжне програмне забезпечення, яке має 4 параметри." Мені було цікаво, наскільки експрес здатний запускати точні посередники оброблювача помилок. Дякую!
Абхішек Агарвал

75

ІМХО, прийнята відповідь на це питання насправді не є точною. Як заявили інші, це дійсно стосується контролю, коли буде запущений наступний обробник ланцюга. Але я хотів надати трохи більше коду, щоб зробити його більш конкретним. Скажіть, у вас є це просте експрес-додаток:

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

Якщо ти зробиш

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

ви побачите це надруковано на консолі:

before request handler
handling request
after request handler

Тепер, якщо ви прокоментуєте дзвінок до next()середнього обробника так:

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

Ви побачите це на консолі:

before request handler
handling request

Зауважте, що останній обробник (той, що друкує) after request handler ) не працює. Це тому, що ви більше не говорите експрес, щоб запустити наступний обробник.

Тому насправді не важливо, чи був ваш "основний" обробник (той, який повертає 200), був успішним чи ні, якщо ви хочете, щоб решта середніх програм працювала, вам потрібно зателефонувати next().

Коли це стане в нагоді? Скажімо, ви хочете реєструвати всі запити, які надходили до якоїсь бази даних, незалежно від того, вдався запит чи ні.

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

Якщо ви хочете, щоб другий обробник працював, вам потрібно зателефонувати next()в перший обробник.

Пам'ятайте, що вузол є асинхронним, тому він не може знати, коли закінчився зворотний дзвінок першого обробника. Ви повинні сказати це, зателефонувавши next().


Sonfar найкраща відповідь для мене.
Норайр Гукасян

Ну пояснення!
Чанг

7

next () без параметра викликає наступний обробник маршруту АБО наступне проміжне програмне забезпечення у рамках.


2
Або наступне проміжне програмне забезпечення.
robertklep

1

Це просто означає передати управління наступному оброблювачу.

Ура


1

Помітьте виклик вище до наступного (). Виклик цієї функції викликає наступну функцію програмного забезпечення в додатку. Наступна () функція не є частиною Node.js або Express API, але є третім аргументом, який передається функції середнього програмного забезпечення. Наступна () функція може бути названа чим завгодно, але за умовою вона завжди називається "наступна". Щоб уникнути плутанини, завжди використовуйте цю умову.


0

Також було задано запитання про використання наступного ("маршруту"), який, здається, покритий тижнем у наданих відповідях:

  1. ВИКОРИСТАННЯ наступного ():

Коротше кажучи: наступна функція програмного забезпечення.

Витяг з цієї офіційної документації Express JS - сторінка "письмова програма" :

"Функція посередництва myLogger просто друкує повідомлення, після чого передає запит наступній функції середнього програмного забезпечення в стеку, викликаючи функцію 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)

На цій сторінці документації Express JS зазначено: "Якщо поточна функція програмного забезпечення не закінчує цикл відповіді на запит, вона повинна зателефонувати next (), щоб передати управління наступній функції середнього програмного забезпечення. В іншому випадку запит буде залишений висячим."

  1. ВИКОРИСТАННЯ наступного ("маршруту"):

Коротше кажучи: наступний маршрут (проти наступної функції середнього програмного забезпечення) у разі next ())

Витяг з цієї документації Express JS - сторінка "з використанням середнього програмного забезпечення" :

"Щоб пропустити решту функцій програмного забезпечення з стека середнього програмного забезпечення маршрутизатора, зателефонуйте next ('route'), щоб передати управління наступному маршруту . ПРИМІТКА. app.METHOD () або router.METHOD ().

У цьому прикладі показаний підрядок середнього програмного забезпечення, який обробляє GET-запити до / 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 () - аргумент зворотного виклику до функції проміжного програмного забезпечення з req, і таким чином є http запитом та аргументами відповіді next у наведеному нижче коді.

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

Тож next () викликає функцію переданого в середньому програмному забезпеченні. Якщо поточна функція проміжного програмного забезпечення не закінчує цикл відповіді на запит, вона повинна викликати наступний (), інакше запит буде залишений і вичерпається.

next () fn потрібно викликати в межах кожної функції проміжного програмного забезпечення, коли декілька функцій проміжного програмного забезпечення передано в app.use або app.METHOD, інакше наступна функція програмного забезпечення не буде викликана (у випадку, якщо передано більше 1 функції середнього програмного забезпечення). Щоб пропустити виклик решти функцій програмного забезпечення середнього програмного забезпечення, зателефонуйте на наступний ('маршрут') в межах функції проміжного програмного забезпечення, після чого жодних інших функцій проміжного програмного забезпечення не слід викликати. У наведеному нижче коді буде викликано fn1, а також fn2, оскільки next () викликається в межах fn1. Однак fn3 не буде викликатися, оскільки next ('route') викликається в 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();
})
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.