yaofly2012 / note

Personal blog
https://github.com/yaofly2012/note/issues
44 stars 5 forks source link

expressjs- Study #39

Open yaofly2012 opened 5 years ago

yaofly2012 commented 5 years ago

What is Express ?

一、概述

  1. 基于Nodejs的Web框架。
  2. slogan:
    • Fast(快速) 对比数据?
    • Unopinionated(开放) 是什么是开放?
    • Minimalist (极简) 怎么讲?

二、构成

express = 路由匹配(routing) + 中间件(middleware) ?

核心概念:

  1. 中间件
  2. 路由匹配
  3. 视图引擎
  4. 静态文件
yaofly2012 commented 5 years ago

路由

app.METHOD(PATH, HANDLER)

路由匹配(route) & 路由对象(router)

  1. 路由匹配是谁负责的? app和router对象貌似都在做?
  2. Router对象有多个method, 每个method又对应多个处理函数;
  3. Use the express.Router class to create modular, mountable route handlers 使用Router方法创建模块化的,可挂载的路由处理函数。可以实现子路由匹配。

多handlers的绑定方式注意:

app.get('/user/:id', function (req, res, next) {
   next()
}, function(req, res, next) {
    res.send('regular')
})
// 而不是多次调用app.METHOD(即使path相同也是多个路由,不是多个Handler)
app.get('/user/:id', function (req, res, next) {
    if(req.params.id === '0') next('route');
    else next()
})
app.get('/user/:id', function (req, res, next) {
    if(req.params.id === '0') next('route');
    else next()
})
  1. app.METHOD 和app.use的区别?
  2. express.Router实例对象 一个express APP可以使用一个Router实例对象处理路由,也可以使用多个Router实例对象处理路由。

路由匹配 ??

  1. common规则的路由放在special规则路由的后面
  2. 下面两种方式路由匹配规则不一样居然?
    
    app.use('/', (req, res) => {
    res.send('Welcome My Site')
    });

app.use('/', Router对象);



## API
1. express.Router
2. app.route
3. app.METHOD(PATH, HANDLER)

是中间件语法糖?

# 参考
1. [Differences between express.Router and app.get?](https://stackoverflow.com/questions/28305120/differences-between-express-router-and-app-get)
yaofly2012 commented 5 years ago

express.static函数

  1. 静态目录下Index.html文件处理(貌似会自动追加index.html)
yaofly2012 commented 5 years ago

中间件

就是个函数function(req, res, next) {}

能做什么

  1. 修改req, res(所有中间件共享req,res对象)
  2. 终止req-res cycle

加载中间件&中间件队列

app.use方法,

next函数

  1. 也是个中间件函数,不处理res的中间件函数,一定要调用next函数转移req-rep控制权,要不然请求一直被挂起状态。
  2. next('route') 和next('router')区别

    next('route') to pass control to the next route. next('router') to pass control back out of the router instance.

所以routerouter的区别? route是路由,而router是express的概念是Router的实例对象。Router对象也可以有多个route(即子路由),路由可以依据path的分层结构而分层表示。

  1. next(error) 直奔错误处理中间件。

request-response cycle ?

由中间件函数构成了一个队列,中间件就像流水线各个节点,req-res进过这些中间件被处理。

next函数的调用和handler调用关系?

app.use(function myLogger(req, res, next) {
    console.log('myLogger1 before')
    next();
    console.log('myLogger1 after')
})

app.use(function myLogger(req, res, next) {
    console.log('myLogger2 before')
    next();
    console.log('myLogger2 after')
})

app.get('/', (req, res) => {
    console.log('handle')
    res.send('Hello World!')
})

the possibilities with middleware functions are endless

中间件的功能无限大。

yaofly2012 commented 5 years ago

express异常处理机制

捕获

原则上express能捕获req-res cycle中的异常,异步代码会脱离express控制,需要显示处理。

  1. express会自动处理中间件或者路由处理函数里同步代码抛出的异常,生成500点response;
  2. 异步代码触发的异常需要显示传给next函数,否则express捕获不到的。

next函数怎么根据参数执行不同行为的?

调用next函数传参不同,express行为不同,怎么判断参数的

next(), next('route'), next('router'), next(error)

处理

参考

可参考NodeJS: 如何在 Express 中处理异步错误

yaofly2012 commented 5 years ago

其他

  1. 代理
  2. debugger
yaofly2012 commented 5 years ago

其他话题& 讨论

1. What is Node.js' Connect, Express and “middleware”?

2. 区分中间件和路由匹配处理函数

app.use('/hello', function fn1(req, res, next) {
    res.send('hello World')
})

app.get('/hello', function fn2(req, res, next) {
    res.send('hello World')
})
  1. fn1是添加中间件,fn2是添加路由处理函数;
  2. 只要请求的父路径是'/hello'时(如'/hello', '/hello/a',)都会执行fn1,而只有当请求时'/hello'时才会执行fn2。
yaofly2012 commented 5 years ago

重新认识express

Route(路由)

路由path

  1. 相对于该Route的Router的path?

类型

  1. 字符串 精确匹配的(但大小写不敏感)
    app.get('/book', (req, res) => { res.send('book') })

    匹配:

    • /book
    • /booK
    • /book/
  2. 字符串模式 精确匹配的(但大小写不敏感)
  3. 正则表达式

路由参数(路径参数)

  1. 命名的路径片段
  2. 对路径参数添加额外的格式校验
  3. 通过request.params对象获取路径参数

路由处理器

  1. 格式:可以是一个函数,也可以是个函数数组,或者前两种的组合;
  2. next('route')逻辑

链式路由处理函数

create chainable route handlers Because the path is specified at a single location, creating modular routes is helpful, as is reducing redundancy and typos.

app.route(path)

如果对单一路径绑定指定对多种method对处理函数可以使用route方法。

  1. all方法会绑定所有

modular routes(模块化路由)

Use the express.Router class to create modular, mountable route handlers.

把路由处理函数通过模块文件的方式组织,让项目结构更清晰,方便维护。

express.Router

中间件

中间件能干什么

  1. Execute any code 中间件本质就是个函数,可以执行任何代码逻辑。但注意:如何该中间件函数没有终止req-res,则必须调用next函数,进入下一个中间件函数,否则请求会一直被挂起等待处理。
  2. Make changes to the request and the response objects. 在整个req-res循环过程中,reqres对象都是公用对对象,可以在上面添加自定义属性,把自己处理对结果添加到req或者res对象上。好多中间件处理函数都是这样做对。
  3. End the request-response cycle. ?怎么判断是否被终止的
  4. Call the next middleware function in the stack. 了解中间件处理系统

一切都是中间件

express app -> Router -> Route -> Request Handlers 都是中间件。

  1. 各中间件调用节点?

中间件处理系统

  1. next()流转到下一个处理函数;
  2. next(route)跳过当前route到剩余处理函数,流转到下一个route;
  3. next(router)跳过当前router剩余到route,流转到下一个router;
  4. next(error) ?

错误处理(Error Handling)

Express捕获,处理异常机制。

捕获异常

路由处理函数和中间件函数内部可以执行任意同步或者异步代码,如果代码执行发生异常并且想让Express处理这些异常,则必须告诉Express发生异常了(即让Express捕获到异常)。

  1. 同步代码异常捕获 不需要额外逻辑,Express会自动捕获。怎么做到的?
  2. 异步代码异常捕获 必须显示的把错误对象传给next函数,否则Express无法处理,需要开发自己处理,如果开发也没处理则一直往上抛了,应用就挂了。 next函数如何区分各种不同实参调用逻辑的?

If you had done this processing inside the readFile callback then the application might exit and the Express error handlers would not run.

啥意思?

异常处理

  1. 默认异常处理中间件

    So when you add a custom error handler, you must delegate to the default Express error handler, when the headers have already been sent to the client.

这是因为默认异常处理中间件会

the Express default error handler closes the connection and fails the request.

????

  1. 异常处理中间件和一般中间件异同: ???

    实现

    异常处理也是个中间件。那是如何被执行到呢?

    If you pass anything to the next() function (except the string 'route'), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.