이 글은 주로 nodejs의 express에서 다음 기능에 대한 이해를 소개합니다. 관심 있는 친구들이 참고할 수 있습니다.
최근 회사에서는 node를 사용하여 프론트엔드와 백엔드를 분리하고 있으며, 웹 프레임워크를 사용하고 있습니다. express 이기 때문에 express 프레임워크에 대해 심도있게 이해하게 되었습니다. 얼마전에 express 라우팅에 대한 글을 썼는데, express의 다음 글인 그 글에는 아주 중요한 내용이 빠져있는 것 같아서 오늘은 Express에 대해서는 다음에 별도로 이야기하겠습니다.
next에 대해서는 크게 3가지 측면에서 설명하겠습니다.
next의 역할은 무엇인가요?
다음은 언제 써볼까?
next의 내부 구현 메커니즘은 무엇인가요?
Next의 역할
Express 미들웨어 함수를 정의할 때 세 번째 매개변수를 next로 정의하겠습니다. 오늘의 next 함수는 주로 다음 미들웨어에 제어권을 넘겨주는 역할을 합니다. 현재 미들웨어가 요청을 종료하지 않고 다음이 호출되지 않으면 요청이 일시 중지되고 나중에 정의된 미들웨어가 실행될 기회가 없습니다.
Next를 사용해야 하는 경우
위의 설명에서 우리는 next 함수가 등록된 모든 미들웨어가 하나씩 실행되도록 주로 사용된다는 것을 이미 알고 있습니다. 그런 다음 모든 미들웨어에서 next 함수를 호출해야 하지만, 특별한 경우, 우리가 정의한 미들웨어가 이 요청을 종료하면 다음 함수를 호출하면 안 됩니다. 그렇지 않으면 문제가 발생할 수 있습니다.
app.get('/a', function(req, res, next) { res.send('sucess'); next(); }); // catch 404 and forward to error handler app.use(function(req, res, next) { console.log(404); var err = new Error('Not Found'); err.status = 404; next(err); }); app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); });
Send request"/a " 코드를 보면 콘솔이 다음과 같이 로그를 인쇄합니다.
404 GET /a 500 6.837 ms - - Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:345:11)
코드에서 예외가 발생하는 이유는 res.send 이후에 다음 함수를 호출했기 때문입니다. 비록 이번 요청은 종료되었지만 그 뒤에 있는 404 미들웨어는 계속 실행될 예정입니다. 후속 미들웨어는 res의 헤더에 속성 값을 추가하려고 시도하므로 위 예외가 발생합니다.
이 글을 읽고 궁금한 점이 있을 수 있습니다. res.send 이후 다음 함수를 호출하지 않으면 나중에 정의된 404 미들웨어가 실행되지 않습니까? 이제 res.send 이후 다음 함수 호출을 삭제하고 "/xxx" 요청을 보내면 404 미들웨어가 실행되는 것을 볼 수 있습니다. (ㄒoㄒ) 이는 앞서 말한 내용과 모순되지 않습니까? 미들웨어는 다음을 호출하지 않지만 나중에 정의된 미들웨어는 계속 실행됩니다. 이유는 무엇입니까? 소스코드에서만 도움을 요청할 수 있는 것 같습니다~~
Next의 내부 메커니즘
function next(err) { ... //此处源码省略 // find next matching layer var layer; var match; var route; while (match !== true && idx < stack.length) { layer = stack[idx++]; match = matchLayer(layer, path); route = layer.route; if (typeof match !== 'boolean') { // hold on to layerError layerError = layerError || match; } if (match !== true) { continue; } ... //此处源码省略 } ... //此处源码省略 // this should be done for the layer if (err) { layer.handle_error(err, req, res, next); } else { layer.handle_request(req, res, next); } }
위는 문제를 더 쉽게 설명하기 위해 next의 소스코드입니다. , 코드가 삭제되었습니다. 위의 소스 코드에서 다음 함수 내부에 while 루프가 있음을 알 수 있습니다. 각 루프는 스택에서 레이어를 가져옵니다. 이 레이어에는 라우팅 및 미들웨어 정보가 포함되어 있으며 해당 레이어는 요청된 것과 일치하는 데 사용됩니다. 일치에 성공하면 layer.handle_request가 실행되고 미들웨어 함수가 호출됩니다. 그러나 일치가 실패하면 다음 레이어(미들웨어)가 반복됩니다.
이제 위에서 제기한 문제, 즉 사용자 정의 미들웨어에서 다음 함수가 호출되지 않지만 요청한 "/xxx"가 일치할 수 없기 때문에 후속 404 미들웨어가 계속 실행되는 이유를 설명할 수 있습니다. 등록된 "/a" 라우팅 미들웨어이므로 while 루프는 계속 실행되고 일치하는 404 미들웨어가 성공하므로 404 미들웨어가 실행됩니다.
참고: app.use에 등록된 미들웨어의 경우 경로 매개변수가 비어 있으면 기본값은 "/"이고 경로가 "/"인 미들웨어는 기본적으로 모든 요청과 일치합니다.
한 가지 특별히 짚고 넘어가야 할 점은 사실 라우팅 미들웨어를 정의할 때 함수 옆의 세 번째 매개변수는 비라우팅 미들웨어를 정의할 때의 함수 옆의 세 번째 매개변수와 동일하지 않다는 것입니다. 위에서 봤습니다. Non-Routing 미들웨어의 다음이고, 라우팅 미들웨어의 다음 기능은 이렇습니다
function next(err) { if (err && err === 'route') { return done(); } var layer = stack[idx++]; if (!layer) { return done(err); } if (layer.method && layer.method !== method) { return next(err); } if (err) { layer.handle_error(err, req, res, next); } else { layer.handle_request(req, res, next); } }
다음은 위의 것보다 훨씬 간단합니다. 여러 미들웨어의 제어권을 넘겨주는 역할을 합니다. 그리고 "route" 매개변수를 받게 됩니다. next("route")가 호출되면 현재 경로의 다른 미들웨어를 건너뛰고 제어권을 다음 경로로 직접 이전합니다.
마지막으로 next(err)에 대해 이야기할 필요가 있습니다. next(err)가 어떻게 제어를 오류 처리 미들웨어로 전달하는지 이전 코드에서 우리는 next(err)가 호출되면 express가 내부적으로 레이어를 호출한다는 것을 알고 있습니다. .handle_error, 그러면 소스 코드를 살펴보겠습니다
Layer.prototype.handle_error = function handle_error(error, req, res, next) { var fn = this.handle; if (fn.length !== 4) { // not a standard error handler return next(error); } try { fn(error, req, res, next); } catch (err) { next(err); } };
코드의 fn은 미들웨어 함수입니다. Express는 fn의 매개변수 개수를 판단합니다. 오류 처리 중간 파일이 아닌 것으로 간주되면 계속해서 next(err)를 호출하여 다음 미들웨어 함수에 들어가 특정 미들웨어의 매개변수 수까지 계속해서 매개변수 수를 판단합니다. 함수가 4이면 오류 처리가 발견된 것으로 간주하고 해당 미들웨어 함수를 실행합니다.
위 내용은 nodejs의 express에서 next 함수의 사용법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!