Vue2+Echarts+koa2+websocket e-commerce platform data visualization real-time detection system back-end project construction (2)

 1. KOA2——  Web server framework based on Node . js platform

Built by  the original team of Express

Both Express   Koa  and  Koa 2 are frameworks for  web servers , and the differences and relationships between them can be expressed in the table below

framework name

effect

asynchronous processing

Express

web framework

callback function

So

web framework

Generator+yield

Koa2 _ 

web framework

async/await

  The environment depends on  Node    v7.6.0 and above

Since  Koa2 supports  async and await , it has requirements for the version of Node . It requires the version of Node to be at least level 7.6 , because the syntactic sugar async and await is only supported after Node 7.6          

 1.1 Middleware of the onion model

As shown in the figure below , for the server, it is actually to process one request after another.    After the web server receives one request after another sent by the browser  , it forms one response after another and returns it to the browser . The request to reach our server needs to be processed by the program . After the program is processed, a response will be formed and returned to the browser. The program that our server processes the request is called middleware in the world of Koa 2 .  

 This kind of middleware may not only have one, but there may be multiple ones. For example, as shown in the figure above , it has  three The process of processing requests and the order of its calls are as follows :

  When a request arrives at our server, the first layer of middleware is the first to process the request

  After the first-tier middleware processes the request, it will pass the request to the second-tier middleware

  After the second-tier middleware processes the request, it will send the request to the third-tier middleware

There is no middleware inside   the third- tier middleware , so after the third-tier middleware has processed all the codes, the request returns

It will reach the second-level middleware, so the second-level middleware has processed this request twice

  After processing the request, the middleware of the second layer reaches the middleware of the first layer , so the middleware of the first layer also responds to this request.

requests were processed

This call sequence is the onion model . The middleware has a first-in-last-out feeling in processing requests. The request first reaches the first-level  middleware , and finally the first-level middleware processes the request again.

2. Quick start of KOA2

 Check  the version of Node 

The node  - v  command can help us check  the version of Node  . The use of Koa 2 requires Node version 7.6 and above  

Install  Koa 2

This command can quickly create a  package.json file , which can maintain the information of the third-party package in the project 

npm  install  koa

This command can download the latest version of koa online  to the current project . Since the latest version of koa online is koa 2 , we don't need to execute npm install koa 2       

Write the entry file  app.js and create an instance object of Koa  

//  1. Create koa object _

const  Koa  = require ( ' koa ' ) // import constructor

const  app  =  new  Koa () // Create an instance object through the construction method

  Write a response function ( middleware )

The response function can only be effective through use . This function has two parameters , one is ctx and the other is next  ctx :     

Context refers to the web container where the request is located . We can get the request object through ctx.request , or get the response object through ctx.response  

  next : the entry point for inner middleware execution

// 2. Write the response function ( middleware )

app.use((ctx, next) => {

console.log(ctx.request.url)

ctx.response.body = 'hello world'

})

Specify the port number: You  can specify a port number through app.listen

// 3. Bind port number 300 0

app.listen(3000)

 Start the server: You can start the server through  node  app . js 

Then open the browser , enter 127.0.0.1:3000/ in the browser, you will see the string of hello world appear in the browser , and you can also see the requested url in the terminal of the server        

3. Features of  KOA2middleware

The instance object of Koa 2 adds a middleware through the use method. A middleware is a function . This function has two parameters , namely ctx and next . The execution of middleware conforms to the onion model. Whether the inner middleware can be executed depends on whether the next function of the outer middleware is called. Call the next function to get the Promise object . If you want to get the data wrapped by the Promise , you can combine await and async          

app.use(async (ctx, next) => {

//  Just enter what the middleware wants to do

await next()

// What you want to do after all the middleware in the inner layer ends

})

4. Development of background

4.1. The goal of the background project

The background project needs to achieve the following goals :

1. Calculate the total time spent by the server processing the request

Calculate the total time spent by the server on all middleware for this request

2. Add the mime type of the response content to the response header

Adding the mime type allows the browser to better handle the data returned by the server .

If the response to the front-end browser is data in json  format, then we need to add Type in our response header and  its value is application/json , which is the mime type of json data type

3. Read the content of the file in the specified directory according to the URL

In order to simplify the code of the background server, the data required by the front-end chart does not exist in the database , but will be stored in the file. This operation is only to simplify our background code . So we need to read a certain directory The content  of the file below .

Each goal is a function that a middleware needs to implement , so there need to be three middleware in the background project

4.2. Development steps of the background

Create a new folder called koa_server , which is the folder of the background  project 

   1. Installation package

npm init -y

npm  install  koa

   2. Create the file and directory structure

 Code directory structure

 app.js is the entry file of the background server

The data  directory is used to store the  json file data of all modules

middleware is used to store all middleware code

koa_response_data.js is business logic middleware _ _ _

koa_response_duration.js is a middleware for calculating server processing time

koa_response_header.js is a middleware used to specifically set the response header

Then copy the  json data files of each module to  the data  directory , and then  write the code in the app.js file as follows :

// server entry file

// 1. Create an instance object KOA

const  Koa  = require ( ' koa ' )

const  app  = new  Koa ( )

// 2. Bind middleware

// Bind the first layer middleware

// Bind the second layer middleware

// Bind the third layer middleware

// 3. Bind port number 888 8

app.listen(8888)

   4.3. Total time-consuming middleware

   1. Layer 1 middleware

        The function of the total time-consuming middleware is to calculate the total time-consuming of all middleware on the server, which should be located in the first layer, because the middleware in the first layer  is the middleware that processes the request first When entering our middleware for the first time, record a start time. After all other middleware are executed, record the end time and subtract the two to get the total time.

    

   3. Set the response header

        将计算出来的结果,设置到响应头的 X-Response-Time , 单位是毫秒 ms

具体代码如下:

app.js 

// 绑定第一层中间件

const respDurationMiddleware =

require('./middleware/koa_response_duration')

app.use(respDurationMiddleware)

koa_response_duration.js

// 计算服务器消耗时长的中间件

module.exports = async (ctx, next) => {

// 记录开始时间

const start = Date.now()

// 让内层中间件得到执行

await next()

// 记录结束的时间

const end = Date.now()

// 设置响应头 X-Response-Time

const duration = end - start

// ctx.set 设置响应

ctx.set('X-Response-Time', duration + 'ms')

}

   4.4 响应头中间

   1.2层中间件

        这个第2层中间件没有特定的要

       

   2.获取 mime类型

        由于响应给前端浏览器当中的数据都是 json 格式的字符串,所以 mime 类型可以统一

的给它写成 application/json , 当然这一块也是简化的处理了,因为 mime 类型有几十几百 种,,所以这里简化处理一下

   3.设置响应

        响应头的keyContent-Type ,它的值是 application/json , 顺便加上 charset=utf-8

告诉浏览器,我这部分响应的数据,它的类型是 application/json ,同时它的编码是具体代码如下:

app.js

// 绑定第二层中间件
const respHeaderMiddleware = require('./middleware/koa_response_header')
app.use(respHeaderMiddleware)

koa_response_header.js

 

// 设置响应头的中间件
module.exports = async (ctx, next) => {
  const contentType = 'application/json; charset=utf-8'
  ctx.set('Content-Type', contentType)
  await next()
}

   4.5 业务逻辑中间

   1.3层中间件

        第三层中间件处理实际的业务逻辑,处理前端请求并返回

        

   2.读取文件内容

          获取 URL 请求路径

const url = ctx.request.url

  根据URL请求路径,拼接出文件的绝对路

let filePath = url.replace('/api', '')

filePath = '../data' + filePath + '.json'

filePath = path.join(__dirname, filePath)

 filePath就是需要读取文件的绝对路径

  读取这个文件的内

使 fs模块中的 readFile方法进行实现

   3.设置响应

ctx.response.body

具体代码如下:

app.js

// 绑定第三层中间件

const respDataMiddleware = require('./middleware/koa_response_data') app.use(respDataMiddleware)

koa_response_data.js

// 处理业务逻辑的中间件 ,读取某个json文件的数据
const path = require('path')
const fileUtils = require('../utils/file_utils')
module.exports = async (ctx, next) => {
// 根据url
const url = ctx.request.url // /api/seller   ../data/seller.json
let filePath = url.replace('/api', '') //  /seller
filePath = '../data' + filePath + '.json'  // ../data/seller.json
filePath = path.join(__dirname, filePath)
try {
const ret = await fileUtils.getFileJsonData(filePath)
ctx.response.body = ret
} catch (error) {
const errorMsg = {
message: '读取文件内容失败 , 文件资源不存在', status: 404
}
ctx.response.body = JSON.stringify(errorMsg) }
console.log(filePath)
await next()
}

file_utils.js

// 读取文件的工具方法
const fs = require('fs')
module.exports.getFileJsonData = (filePath) => {
  // 根据文件的路径, 读取文件的内容
  return new Promise((resolve, reject) => {
    fs.readFile(filePath, 'utf-8', (error, data) => {
      if(error) {
        // 读取文件失败
        reject(error)
      } else {
        // 读取文件成功
        resolve(data)
      }
    })
  })
}

   4.6 允许跨域

  设置响应头koa_response_header.js 添加

// 设置响应头的中间件
module.exports = async (ctx, next) => {
  const contentType = 'application/json; charset=utf-8'
  ctx.set('Content-Type', contentType)
  ctx.set("Access-Control-Allow-Origin", "*")
  ctx.set("Access-Control-Allow-Methods", "OPTIONS, GET, PUT, POST, DELETE")
  await next()
}

5.引入webScoket

WebSocket以保持着浏览器和客户端之间的长连接,   通过 WebSocket可以实现数据由后端推送到前 端,保证了数据传输的实时性. WebSocket涉及到前端代码和后端代码的改

5.1. WebSocket 的使用

  安装 WebSocket

npm i ws -S

创建 service\web_socket_service.js 文件

 创建 WebSocket实例对象

const WebSocket = require('ws')
// 创建WebSocket服务端的对象, 绑定的端口号是9998
const wss = new WebSocket.Server({
  port: 9998
})
wss.on("connection", client => {
console.log("有客户端连接 ...")
client.on("message", msg => {
console.log("客户端发送数据过来了")
// 发送数据给客户端
client.send('hello socket')
})
})

监听事件

 app.js 中引入 web_socket_service.js 这个文件, 并调用 listen 方法

const webSocketService = require('./service/web_socket_service') 
webSocketService.listen()

5.2 约定客户端之间数据交互格式

客户端和服务端之间的数据交互采用 JSON 格式

  客户端发送数据给服务端的字段如下:

{
"action": "getData",
"socketType": "trendData",
"chartName": "trend",
"value": ""
}
或者
{
"action": "fullScreen",
"socketType": "fullScreen",
"chartName": "trend",
"value": true
}
或者
{
"action": "themeChange",
"socketType": "themeChange",
"chartName": "",
"value": "chalk"
}

 其:

  action : 代表某项行,可选值有

  •  getData 代表获取图表数据
  •  fullScreen 代表产生了全屏事件
  • themeChange 代表产生了主题切换的事件

socketType : 代表业务模块, 这个值代表前端注册数据回调函数的标识, 可选值有:

  • trendData
  • sellerData
  • mapData
  • rankData
  • hotData
  • stockData
  • fullScreen
  • themeChange 

  chartName : 代表图表名称, 如果是主题切换事件, 可不传此值, 可选值有:

  • trend 
  • seller
  • rank
  • stock

  value : 代表 具体的数据值, 在获取图表数据时, 可不传此值, 可选值有

  如果是全屏事件,  true代表全屏,  false代表非全屏

  如果是主题切换事件, 可选值有 chalk或者 vintage

  服务端发送给客户端的数据如下:

{
"action": "getData",
"socketType": "trendData",
"chartName": "trend",
"value": "",
"data": "从文件读取出来的json文件的内容"
}
或者
{
"action": "fullScreen",
"socketType": "fullScreen",
"chartName": "trend",
"value": true
}
或者
{
"action": "themeChange",    "socketType": "themeChange", "chartName": "",
"value": "chalk"
}

注意, 除了 action getData , 服务器会在客户端发过来数据的基础之上, 增加 data字段, 其他的情况, 服务器会原封不动的将从某一个客户端发过来的数据转发给每一个处于连接状态 客户端

  5.3.代码实现 service\web_socket_service.js 

const path = require('path')
const fileUtils = require('../utils/file_utils')
const WebSocket = require('ws')
// 创建WebSocket服务端的对象, 绑定的端口号是9998
const wss = new WebSocket.Server({
  port: 9998
})
// 服务端开启了监听
module.exports.listen = () => {
  // 对客户端的连接事件进行监听
  // client:代表的是客户端的连接socket对象
  wss.on('connection', client => {
    console.log('有客户端连接成功了...')
    // 对客户端的连接对象进行message事件的监听
    // msg: 由客户端发给服务端的数据
    client.on('message',async msg => {
      console.log('客户端发送数据给服务端了: ' + msg)
      let payload = JSON.parse(msg)
      const action = payload.action
      if (action === 'getData') {
        let filePath = '../data/' + payload.chartName + '.json'
        // payload.chartName // trend seller map rank hot stock
        filePath = path.join(__dirname, filePath)
        const ret = await fileUtils.getFileJsonData(filePath)
        // 需要在服务端获取到数据的基础之上, 增加一个data的字段
        // data所对应的值,就是某个json文件的内容
        payload.data = ret
        client.send(JSON.stringify(payload))
        console.log(payload.data)
      } else {
        // 原封不动的将所接收到的数据转发给每一个处于连接状态的客户端
        // wss.clients // 所有客户端的连接
        wss.clients.forEach(client => {
          console.log("客户端触发"+action+"事件")
          // client.send(msg)
          payload.data = JSON.parse(msg)
          client.send(JSON.stringify(payload) )
        })
      }
      // 由服务端往客户端发送数据
      // client.send('hello socket from backend')
    })
  })
}

Guess you like

Origin blog.csdn.net/qq_36384657/article/details/129311071