【 Express 】 원본 읽 기 기록 (1)
Express 주요 디 렉 터 리 구조
프로젝트 디 렉 터 리 구 조 는 가장 중요 한 부분 을 선택 하여 열 거 했 습 니 다.
├── lib
| ├── middleware
| | ├── init.js
| | └── query.js
├── ├── router //router ,
| | ├── index.js
| | ├── layer.js
| | └── route.js
├── ├── application.js
├── ├── express.js
├── ├── request.js // request
├── ├── reponse.js
├── ├── util.js
├── └── view.js // , res.render()
|
└── index.js
express 와 app
express 에서 가장 많이 나타 나 는 것 은
express
으로 그 중요성 을 알 수 있다.예 를 들 어 가장 간단 한 정적 서버 를 구축 합 니 다.const express = require('express')
const app = express()
app.get('/',function(req,res){
res.send('Hello World!')
res.end()
})
app.listen(3000,function(){
console.log(' ...')
})
다음은 소스 코드 에서 express 와 app 을 분석 합 니 다.
/*
* express.js
*/
// express() app
exports = module.exports = createApplication
//createApplication express main , express
function createApplication(){
var app = function(req,res,next){
app.handle(req,res,next)
}
// mixin
mixin(app,EventEmitter.protprype,false)
mixin(app,proto,false)
app.request = Object.create(req,{...})x
app.response = Object.create(res,{...})
return app
}
상기 코드 의 app. handle, handle 방법 은 application. js 에서 정의 합 니 다.우선 application. js 의 전체적인 구 조 를 살 펴 보 겠 습 니 다.
//application.js
app.init = function init(){
this.cache = {}
this.engines = {}
this.settings = {}
this.defaultConfiguration()
}
//app.
app.render = function render(name,options,callback){...}
app.listen = function listen(){
var server = http.createServer(this);
return server.listen.apply(server, arguments);
}
//
function logederror(err){...}
function tryRender(view,options,callback){...}
app 은 http. createServer 의 인자 로 요청 처리 함수 입 니 다.한편, express 는 공장 함수 로 요청 처리 함 수 를 생 성 하 는 데 사용 된다.왜 express 가 공장 함수 라 고 말 합 니까?정적 서버 를 구축 할 때의 코드 를 증명 할 수 있 습 니 다.
const app = express()
다음은 app. handle () 을 따로 제시 하여 연 구 를 해 보 겠 습 니 다. express. js 에서 mixin 을 통 해 가 져 왔 습 니 다.그 역할 은 각각 [req, res] 를 단계별 로 나 누 어 주 는 것 으로 정 의 된 경로 와 미들웨어 에 작용 하여 마지막 에 완성 하 는 것 이다.
app.handle = function(req,res,callback){
var router = this._router
//final handler
var done = callback||finalhandler(req,res,{
env:this.get('env'),
onerror:logerror.bind(this)
})
//no routes
if(!router){
debug('no routes defined on app')
done()
return
}
router.handle(req,res,done)
}
여기 서 두 가지 관건
app
과
을 제외 하고미들웨어
express 에서 가장 관건 적 인 개념 은 중간 부품 이다.하나의 Express 응용 은 본질 적 으로 일련의 미들웨어 호출 이다.그렇다면 도대체 중간 부품 은 무엇 입 니까?
하나의 중간 부품 은 본질 적 으로 하나의 함수 이 고, 중간 부품 을 호출 하 는 것 은 함수 에 대한 호출 이다.Express 4. x 에서 내 장 된 모든 미들웨어 를 취소 하고 외부 에서 도입 해 야 합 니 다.이러한 개선 은 express 는 독립 된 경로 와 웹 미들웨어 프레임 워 크 로 업데이트 가 더욱 편리 하고 유 닉 스 철학 에 더욱 부합된다.
미들웨어 일반 함수 형식 은 다음 과 같다.
function middleware(req,res,next){
//...
}
이상 처 리 는 비동기 프로 그래 밍 의 어 려 운 점 입 니 다. 우 리 는 일반적인
구문 블록 으로 이상 을 포착 할 수 없습니다.try - catch 는 이번 이벤트 순환 내 이상 만 포착 할 수 있 으 며, callback 실행 에 던 진 이상 은 어 쩔 수 없습니다.따라서 Node 는 처리 이상 에 있어 서 일종 의 약속 을 형성 하여 이상 을 리 셋 함수 의 첫 번 째 실제 인삼 으로 전송 합 니 다. 빈 값 이 라면 처리 오류 미들웨어 함수 형식 을 이상 하 게 던 지지 않 았 음 을 나타 냅 니 다.function middleware(err,req,res,next){
//error
//...
}
다음은 미들웨어 함수 의 인 자 는 req 와 res 를 무시 합 니 다.
try-catch
자체 도 하나의 함수 입 니 다. 호출 next
은 다음 미들웨어 를 계속 실행 합 니 다.요청 프로 세 스 도 해 는 다음 과 같 습 니 다. ↓
---------------
| middleware1 |
---------------
↓
---------------
| ... ... ... |
---------------
↓
---------------
| middlewareN |
---------------
↓
express 를 사용 할 때 우 리 는 이런 코드 를 자주 볼 수 있다.
// /user
app.use('/user',function(req,res,next){...})
// /user
app.get('/user',function(req,res,next){...})
상기 코드 에 따 르 면 중간 부품 은 크게 두 가지 로 나 눌 수 있다.
next()
과
.일반 미들웨어 등록 은 보통
을 통 해 이 루어 지고 등록 로 는 미들웨어 로 보통 app.use()
를 통 해 등록 된다.이 두 가지 방법 은 모두 app.METHOD()
에 의 해 처리 된다.경로 라 우 터
요청 처리 의 상세 한 과정 을 알 고 싶다 면 우선 Router 를 알 아야 한다.우선 Routerde 디 렉 터 리 구 조 를 살 펴 보 겠 습 니 다.
├── router
| ├── index.js
| ├── layer.js
| └── route.js
쉽게 말 하면 Router (원본 코드 는 router / index. js) 는 중간 부품 의 용기 이다.사실 Router 는 Express 에서 매우 핵심 적 인 것 으로 기본적으로 간략화 된 Express 프레임 워 크 이다.app 의 많은 API, 예 를 들 어 app. use (), app. param (), app. handle () 등 은 사실상 Router API 에 대한 간단 한 포장 입 니 다.app.router 는 기본 Router 대상 에 접근 합 니 다.
app. get () 이 어떻게 이 루어 졌 는 지
methods.forEach(function(method){
// JavaScript '[]' '.' .
// , '[]'
app[method] = function(path){
if(method==='get' && arguments.length===1){
//app.get(setting)
return this.set(path)
}
this.lazyrouter()
var route = this._router.route(path)
route[method].apply(route,slice.call(arguments,1))
return this
}
})
상기 코드 를 통 해 우 리 는 Express 가
app.handle
방법 에 대한 추 가 는 모두 동태 적 인 것 이 라 고 보 낼 수 있다.하나의 foreach 순환 이 모든 method 함수 의 정 의 를 해 결 했 습 니 다.함수 의 내부 구현 을 보 세 요. 함수 매개 변수 길이 가 1 이면 this. set (path) 로 바로 돌아 갑 니 다.Express API 를 보면 알 수 있 듯 이 METHOD
두 가지 기능 을 실 현 했 습 니 다. 길이 가 1 이면 app. set () 가 정의 한 변 수 를 되 돌려 주 고 매개 변수 길이 가 1 보다 크 면 경로 처 리 를 합 니 다.이 어
app.get()
소스 코드 로 포 지 셔 닝app.lazyrouter = function lazyrouter(){
if(!this._router){ // _router , new Router
this._router = new Router({
caseSensitive: this.enabled('case sensitive routing'),
strict: this.enabled('strict routing')
})
this._router.use(query(this.get('query parse fn')))
this._router.use(middleware.init(this))
}
}
이 new 에서 나 온 Router 는 본질 적 으로 중간 부품 용기 이다.그리고
this.lazyrouter()
.app 의 많은 API, 예 를 들 어 app. use (), app. param (), app. handle () 등 은 사실상 Router API 에 대한 간단 한 포장 입 니 다.app.router 는 기본 Router 대상 에 접근 합 니 다.이전
Router Express , Express
으로 돌아 가면 this. lazyrouter () 를 실행 한 후에 methods.forEach
는 경로 처리 함 수 를 저장 하 는 용기 로 간단하게 이해 할 수 있 습 니 다. 하나의 Route
속성 은 하나의 배열 이 고 그 중의 모든 항목 은 Layer 대상 이 며 경로 처리 함수 에 대한 포장 입 니 다.var route = this._router.route(path)
상기 코드 에 따라 찾 을 수 있 습 니 다
stack
proto.route = function route(path){
var route = new Route(path)
var layer = new Layer(path,{
sensitive:this.caseSensitive,
strict:this.strict,
end:true
},route.dispatch.bind(route))
layer.route = route
this.stack.push(layer)
return route
}
여기 new 는 하나의
router/index.js
대상 과 하나의 route
대상 을 만 든 다음 에 route 대상 을 layer. route 에 할당 합 니 다.Route 모듈 에 대응 하 는 것 은 route. js 입 니 다. 주로 경로 정 보 를 처리 하 는 것 입 니 다. 모든 경로 에서 Route 인 스 턴 스 를 생 성 합 니 다.한편, Router 모듈 은 index. js 에 대응 하고 Router 는 하나의 경로 의 집합 으로 Router 모듈 에서 여러 개의 경 로 를 정의 할 수 있 습 니 다. 즉, 하나의 Router 모듈 은 여러 개의 Route 모듈 을 포함 합 니 다.위의 코드 를 통 해 우 리 는 모든 express 가 만 든 인 스 턴 스 가 하 나 를 게 으 르 게 불 러 올 것 이라는 것 을 이미 알 고 있 습 니 다.router 가 경로 처 리 를 합 니 다. 이router 는 Router 모듈 입 니 다.
그렇다면
layer
경 로 를 어떻게 구체 적 으로 처리 하 는 지methods.forEach(function(method){
Route.prototype[method] = function(){
var handles = flatten(slice.call(arguments));
for (var i = 0; i < handles.length; i++) {
var handle = handles[i];
if (typeof handle !== 'function') {
var type = toString.call(handle);
var msg = 'Route.' + method + '() requires callback functions but got a ' + type;
throw new Error(msg);
}
debug('%s %o', method, this.path)
var layer = Layer('/', {}, handle);
layer.method = method;
this.methods[method] = true;
this.stack.push(layer);
}
return this;
};
});
application. js 에서 처리 하 는 방식 과 같 습 니 다.호출
route
할 때 새 layer 를 route.MEHOD()
에 놓 습 니 다.위의 분석 을 통 해 Router 는 사실 2 차원 구조 임 을 알 수 있다.예 를 들 어 가능 한 router. stack 구 조 는 다음 과 같다.
----------------
| layer1 |
----------------
↓
---------------- layer2.route.stack ------------ ------------ ------------
| layer2 | ------------------> | layer2-1 |-->| layer2-2 |-->| layer2-3 |
---------------- ------------ ------------ ------------
↓
---------------- layer3.route.stack ------------ ------------
| layer3 | ------------------> | layer3-1 |-->| layer3-2 |
---------------- ------------ ------------
↓
----------------
| ...... |
----------------
↓
----------------
| layerN |
----------------
route.stack
, :app.METHOD-->router.route-->route.METHOD
기타 참조 링크
원본 주소
Express 4.15.4
참조 링크 4
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.