Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0717 #14

Open
LeungKaMing opened this issue Jul 17, 2017 · 0 comments
Open

0717 #14

LeungKaMing opened this issue Jul 17, 2017 · 0 comments

Comments

@LeungKaMing
Copy link
Owner

LeungKaMing commented Jul 17, 2017

接下来的一个月要把心思都集中在学习Node上,组里选择了Koa这个Node框架,所以后续的issue都用于记录学习的过程。

话题

节选自https://chenshenhai.github.io/koa2-note/note/start/quick.html

环境

简单带过,无非就是安装Koa2

npm install koa // 默认是Koa2

示例代码:

const Koa = require('koa')
const app = new Koa()  // 区别于Koa1
// ctx集request跟response于一身
app.use( async ( ctx ) => {
  ctx.body = 'hello koa2'
})
app.listen(3000)

快速理解async / await

async:能令普通函数转换成针对异步的函数,只要使用async声明过就能使用await;
await:遇到await则等await后的函数执行完成再接着执行自身代码,解决了异步函数不停回调的问题。

const Koa = require('koa')
const app = new Koa()

//  洋葱圈的执行顺序:从外到里,从里到外
function getSyncTime() {
  return new Promise((resolve, reject) => {
    try {
      let startTime = new Date().getTime()
      setTimeout(() => {
        let endTime = new Date().getTime()
        let data = endTime - startTime
        console.log(3)
        resolve( data )
      }, 500)
    } catch ( err ) {
      reject( err )
    }
  })
}

async function getSyncData() {
  console.log('2: before')
  let time = await getSyncTime()
  console.log('2: after')
  let data = `endTime - startTime = ${time}`
  return data
}

async function getData() {
  console.log('1: before')
  let data = await getSyncData()
  console.log('1: after')
  console.log( data )
}

getData()

app.use( async ( ctx ) => {
  ctx.body = 'hello koa2'
})

app.listen(3000)

输出结果为:1:before,2:before,3,2:after,1:after.从上述案例可以得出:

  • 可以让异步逻辑用同步写法实现
  • 最底层的await必须返回的是Promise对象
  • 可以通过多层 async function 的同步写法代替传统的callback嵌套

聊聊中间件

  • 中间件肯定是一个函数
  • 客户端发起的请求,只要流经服务端,都会走中间件
  • 中间件有许多用途:有记录日志,有返回处理过的数据,还有各种。。。
const Koa = require('koa')
const app = new Koa()

/** async封装过的函数只要用在Koa2,都肯定会有2个参数:ctx 和 next
 *   - ctx封装了request和response
 *   - 就像上面提到的:最底层的await必须返回的是Promise对象,而执行next这个函数返回的就是Promise对象
 */
app.use( async ( ctx, next ) => {
  console.log(ctx)
  //  console.log(next())
  ctx.body = 'hello koa2'
  await next()
})
app.listen(3000)

说说ctx

上面提到的ctx,我想把控制台中打印的贴出来:

{ 
  request: { 
    method: 'GET',
    url: '/',
    // 请求头的所有信息
    header: {
      host: 'localhost:3000',
      connection: 'keep-alive',
      'cache-control': 'max-age=0',
      'upgrade-insecure-requests': '1',
      'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
      accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
      'accept-encoding': 'gzip, deflate, sdch, br',
      'accept-language': 'zh-CN,zh;q=0.8',
      cookie: '_ga=GA1.1.936162926.1487390889' 
    }
  },
  // 响应头信息
  response: { status: 404, message: 'Not Found', header: {} },
  app: { subdomainOffset: 2, proxy: false, env: 'development' },
  originalUrl: '/',
  req: '<original node req>',
  res: '<original node res>',
  socket: '<original node socket>' 
}

所谓的ctx其实就是对原生Node的Request和Response封装起来。里面主要的无非就是请求头的所有信息 和 响应头的所有信息,而服务端需要的也就只是这些而已。

怎么写路由

简单点,说话的方式简单点。

  • 上面的例子都是中间件没有做任何过滤(也就是所谓的路由规则),就直接把Hello,Koa2打印在页面上。
  • 实际应用上是怎么做呢?具体看一个简单例子:
const Koa = require('koa')
const app = new Koa()

app.use( async ( ctx, next ) => {
  let url = ctx.request.url  // 把请求的地址通过body写在浏览器上
  ctx.body = `hello koa2! And my request url is: ${url}`
})

app.listen(3000)

上面是一个最简单的默认路由。

定制化你的路由

const Koa = require('koa')
const fs = require('fs')
const app = new Koa()

/**
 * 用Promise封装异步读取文件方法
 * @param  {string} page html文件名称
 * @return {promise}      
 */
function render( page ) {
  return new Promise(( resolve, reject ) => {
    let viewUrl = `./view/${page}`
    fs.readFile(viewUrl, "binary", ( err, data ) => {
      if ( err ) {
        reject( err )
      } else {
        resolve( data )
      }
    })
  })
}

/**
 * 根据URL获取HTML内容
 * @param  {string} url koa2上下文的url,ctx.url
 * @return {string}     获取HTML文件内容
 */
async function route( url ) {
  let view = '404.html'
  switch ( url ) {
    case '/':
      view = 'index.html'
      break
    case '/index':
      view = 'index.html'
      break
    case '/todo':
      view = 'todo.html'
      break
    case '/404':
      view = '404.html'
      break
    default:
      break
  }
  let html = await render( view )
  return html
}

app.use( async ( ctx ) => {
  let url = ctx.request.url
  let html = await route( url )
  ctx.body = html
})

app.listen(3000)
console.log('[demo] route-simple is starting at port 3000')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant