[От интерфейса к полному стеку] - Краткое руководство koa

Node.js внешний интерфейс полный стек koa

предисловие

С непрерывным развитием технологий перед инженерами также возлагается все больше и больше обязанностей. Это больше не обрезчик изображений, которому нужно только вырезать изображение и добавить стиль css для выполнения задачи. В следующей статье выполните простой вход и регистрацию, что позволит вам быстро приступить к работе и стать «маленьким инженером с полным стеком», поехали!

15371488705139

коа быстрый старт

Установить

  • Поскольку node.js v7.6.x уже полностью поддерживает синтаксис async/await, убедитесь, что версия узла выше 7.6.
  • Рекомендуется средство управления несколькими версиями для узла: nvm. Как установить тут описывать не буду, есть много онлайн-уроков

// 初始化package.json
npm init

// 安装koa2 
npm install koa

привет мир

Создайте новый index.js и введите следующий код


//index.js

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

app.use( async (ctx, next) => {
  ctx.response.body = '你好,我是内地吴彦祖'
})

app.listen(3333, ()=>{
  console.log('server is running at http://localhost:3333')
})

в нашей командной строке

node index.js

Вы можете увидеть текущий результат:

15371507388772

несколько основных концепций

Друзья промежуточного ПО ctx и далее

В приведенном выше коде мы видим, что после app.use используются 2 параметра,ctxа такжеnext, давайте представим, что делают два парня

ctx

ctx используется в качестве контекста, Koa будет использовать узелrequest, responseОбъекты инкапсулируются в один объект. которыйctx.request,ctx.response. Koa также выполняет прокси-операции с некоторыми часто используемыми свойствами или методами, так что мы можем получить их напрямую через ctx. Например,ctx.request.urlможно записать какctx.url.

next

Роль следующего параметра — передать управление обработкой следующему промежуточному ПО.

15371520197565

Классическая концепция луковичного графа может хорошо объяснить выполнение next, запрос поступает из самого внешнего слоя и выходит из самого внутреннего слоя. Давайте посмотрим на пример

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

app.use(async (ctx, next)=>{
  let startTime = new Date().getTime()
  await next()
  let endTime = new Date().getTime()
  console.log(`此次的响应时间为:${endTime - startTime}ms`)
})

app.use(async (ctx, next) => {
  console.log('111, 然后doSomething')
  await next()
  console.log('111 end')
})

app.use(async (ctx, next) => {
  console.log('222, 然后doSomething')
  await next()
  console.log('222 end')
})

app.use(async (ctx, next) => {
  console.log('333, 然后doSomething')
  await next()
  console.log('333 end')
})

app.listen(3333, ()=>{
  console.log('server is running at http://localhost:3333')
})

Взгляните на беговые результаты:

15371528106452

Что произойдет, если удалить next() функции **'222'**?

15371529369320

Видно, что следующее промежуточное ПО **'333'** не выполняется напрямую. Таким образом, порядок промежуточного программного обеспечения оказывает большое влияние на выполнение следующего

маршрутизация коа-маршрутизатор

Мы часто используем koa-router для обработки URL-адресов.

Установить

npm i koa-router --save

См. пример:

const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')

const router = new Router()

router.get('/', async (ctx, next) => {
  ctx.body = '你好,我这里是index页'
})

router.get('/user', async (ctx, next) => {
  ctx.body = '你好,我这里是user页'
})

router.get('/error', async (ctx, next) => {
  ctx.body = '你好,我这里是error页'
})

app.use(router.routes())

app.listen(3333, ()=>{
  console.log('server is running at http://localhost:3333')
})

15371540305250

15371540448439
15371540585094

koa-router также поддерживает вложенную запись, загружая все подмаршруты через общий маршрут, что тоже очень удобно. См. пример:

const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')

// 子路由1
let oneRouter = new Router()

oneRouter.get('/', async (ctx, next) => {
  ctx.body = '你好,我这里是oneRouter页'
})

// 子路由2
let twoRouter = new Router()

twoRouter.get('/', async (ctx, next) => {
  ctx.body = '你好, 我这里是twoRouter页'
}).get('/home', async (ctx , next) => {
  ctx.body = '你好, 我这里是home页'
})

// 装载所有子路由
let indexRouter = new Router()

indexRouter.use('/one',oneRouter.routes(), oneRouter.allowedMethods())
indexRouter.use('/two',twoRouter.routes(), twoRouter.allowedMethods())

app
  .use(indexRouter.routes())
  .use(indexRouter.allowedMethods())

app.listen(3333, ()=>{
  console.log('server is running at http://localhost:3333')
})

Взгляните на беговые результаты:

15371560100616
15371560354693
15371560521654

получить данные запроса

koa-router предоставляет общие интерфейсы .get .put .post .del для удовлетворения различных потребностей. В реальной разработке мы используем get и post more, давайте посмотримgetпример:

const Koa = require('koa')
const app = new Koa()
const Router = require('koa-router')
const router = new Router()

router.get('/data', async (ctx , next)=> {
  let url = ctx.url

  // 从ctx的request中拿到我们想要的数据
  let data = ctx.request.query
  let dataQueryString = ctx.request.querystring

  ctx.body = {
    url,
    data,
    dataQueryString
  }
})

app.use(router.routes())

app.listen(3333, ()=>{
  console.log('server is running at http://localhost:3333')
})

Введите http://localhost:3333/data?user=wuyanzu&id=123456 в браузере, вы увидите результат выполнения.

15371636443212

можно увидеть разницу,.queryВозвращаемый результат является объектом, а.querystringОн возвращает строку, которую легко понять. (плагин chrome отображается в формате json)

Например, если он следует спецификации RESTful, запрос должен быть отправлен в форме «/user/:id», мы можем использовать следующий пример для получения желаемых данных.

добавить код

router.get('/data/:id', async (ctx, next) => {

  // 也从ctx中拿到我们想要的数据,不过使用的是params对象
  let data = ctx.params

  ctx.body = data
})

браузер работаетhttp://localhost:3333/data/4396увидеть результаты

15371643392037

Далее посмотримpostпример

Обычно мы запрашиваем сообщение, и его данные помещаются в тело. В настоящее время рекомендуется очень распространенное и простое в использовании промежуточное ПО —koa-bodyparser

Установить первым

npm i koa-bodyparser --save

Затем мы добавляем в код прямо сейчас

router.get('/post', async (ctx, next) => {
    // 模拟一段提交页面
  let html = `    
    <form action="/post/result" method="post">
        <p>你长的最像哪位明星</p>
        <input name="name" type="text" placeholder="请输入名字:"/> 
        <br/>
        <p>输入一段你知道的车牌号</p>
        <input name="num" type="text" placeholder="请输入车牌号:"/>
        <br/> 
        <button>确定不改了哦</button>
     </form> `
  ctx.body = html
})

router.post('/post/result', async (ctx, next) => {
  // 我们可以从ctx的request.body拿到提交上来的数据
  let {name, num} = ctx.request.body

  if (name && num) {
    ctx.body = `hello,你最像的明星是:${name},ch你知道的车牌号是:${num}`
  } else {
    ctx.body = '啊哦~你填写的信息有误'
  }

})

Взгляните на результаты работы

2018-09-17 14 26 24

cache

Коа очень удобно манипулировать кукисами, а также получается из контекста ctx.

  • ctx.cookies.get(name, [options]) прочитать куки в запросе контекста
  • ctx.cookies.set(name, value, [options]) записывать куки в контексте

Добавьте в код нашего почтового запроса прямо сейчас:

router.post('/post/result', async (ctx, next) => {
  // 我们可以从ctx的request.body拿到提交上来的数据
  let {name, num} = ctx.request.body

  if (name && num) {
    ctx.body = `hello,你最像的明星是:${name},ch你知道的车牌号是:${num}`
    ctx.cookies.set(
      'xunleiCode',num,
      {
        domain: 'localhost',  // 写cookie所在的域名
        path: '/post/result',       // 写cookie所在的路径
        maxAge: 10 * 60 * 1000, // cookie有效时长
        expires: new Date('2018-09-17'),  // cookie失效时间
        httpOnly: false,  // 是否只用于http请求中获取
        overwrite: false  // 是否允许重写
      }
    )
  } else {
    ctx.body = '啊哦~你填写的信息有误'
  }

})

Взгляните на беговые результаты:

15371681204265
15371681313023

Если koa управляет сеансом, вам нужно использовать koa-session, 🌰:


const session = require('koa-session')

app.keys = ['some secret hurr'];
const CONFIG = {
  key: 'koa:sess',   //cookie key (default is koa:sess)
  maxAge: 86400000,  // cookie的过期时间 maxAge in ms (default is 1 days)
  overwrite: true,  //是否可以overwrite    (默认default true)
  httpOnly: true, //cookie是否只有服务器端可以访问 httpOnly or not (default true)
  signed: true,   //签名默认true
  rolling: false,  //在每次请求时强行设置cookie,这将重置cookie过期时间(默认:false)
  renew: false,  //(boolean) renew session when session is nearly expired,
};
app.use(session(CONFIG, app));

резюме

Когда дело доходит до областей, с которыми я не сталкивался, я всегда рекомендую сначала посмотреть, как играть, а затем посмотреть, как играть «точно», когда я научусь играть. Благодаря приведенному выше коду и описанию у нас уже есть предварительное представление и концепция коа и узла. В следующей статье мы рассмотрим разделение промежуточного программного обеспечения, модульное тестирование, ведение журнала, спецификации управления и т. д. Давайте расти вместе!

Широкая реклама

Эта статья была опубликована вЕженедельный выпуск Mint Front End, Добро пожаловать в Watch & Star ★, пожалуйста, указывайте источник при перепечатке.

Добро пожаловать, чтобы обсудить, поставить лайк и перейти 。◕‿◕。~