• 数据可视化项目基础知识


    一  Koa2 

    (1)简介

    基于Node.js平台的web开发框架
    由Express原班人马打造
    环境依赖Node v7.6.0及以上

     Koa2特点
    ●支持async\await
    ●洋葱模型的中间件

    (2)步骤

    ●检查Node的环境
    node -V
    ●安装Koa
    npm init -y
    npm install koa
    ●创建并编写app.js文件
       1.创建Koa对象
       2.编写响应函数(中间件)
       3.监听端口
    ●启动服务器
    node app.js

    1. const Koa=require('koa')
    2. const app=new Koa()
    3. // 编写响应函数(中间件)
    4. // ctx:上下文,web容器,ctx.request ctx.response
    5. // next: 下一个中间件,下一层中间件是否能够得到执行, 取决于next这个函数有没有被调用
    6. app.use((ctx,next)=>{
    7. console.log(ctx.request.url)
    8. //设置响应体
    9. ctx.response.body='hello world'
    10. })
    11. app.listen(3000)

    (3)中间件特点

    ●Koa对象通过use方法加入- 个中间件
    ●一个中间件就是一个函数
    ●中间件的执行顺序符合洋葱模型
    ●内层中间件能否执行取决于外层中间件的next函数是否被调用
    ●调用next函数得到的是Promise对象

    1. app.use(async(ctx,next)=>{
    2. //刚进入中间件想做到事情
    3. await next()
    4. //内层所有中间件结束后想做的事情
    5. })

    二 后台项目

      后台项目的目标:
    ●1.计算服务器处理请求的总耗时
    ●2.在响应头.上加上响应内容的mime类型
    ●3.根据URL读取指定目录下的文件内容

    后台项目的实现步骤:
    ●1.项目准备
    ●2.总耗时中间件
    ●3.响应头中间件
    ●4.业务逻辑中间件
    ●5.允许跨域

    =========================================================================(1)项目准备

         ●1.安装包
           npm init -y
           npm install koa
         ●2.创建文件和目录结构
            app.js
            data/
            middleware/
                           koa_ response_ data.js(处理业务逻辑的中间件,读取某个json文件的数据)
                           koa_ response_ _duration.js(计算服务器消耗时长的中间件)
                            koa_ response_ header.js(设置响应头的中间件)
            utils/
                             file_ utils.js(读取文件的工具方法)

          (2).总耗时中间件

              ●1.第1层中间件
              ●2.计算执行时间
                   一进入时记录开始时间,其他所有中间件执行完后记录结束时间,两者相减
              ●3.设置响应头
                   X-Response-Time:5ms

    1. // 计算服务器消耗时长的中间件
    2. module.exports = async (ctx, next) => {
    3. // 记录开始时间
    4. const start = Date.now()
    5. // 让内层中间件得到执行
    6. await next()
    7. // 记录结束的时间
    8. const end = Date.now()
    9. // 设置响应头 X-Response-Time
    10. const duration = end - start
    11. // ctx.set 设置响应头
    12. ctx.set('X-Response-Time', duration + 'ms')
    13. }

    (3)响应头中间件
       ●1.第2层中间件
       ●2.获 取mime类型
            application/json
       ●3.设置响应头
           Content-Type:application/json; charset=UTF-8

    1. async (ctx, next) => {
    2. const contentType = 'application/json; charset=utf-8'
    3. ctx.set('Content-Type', contentType)
    4. await next()
    5. }

    (4)业务逻辑中间件
    ●1.第3层中间件
    ●2.读取文件内容
    获取请求的路径,拼接文件路径
    读取该路径对应文件的内容
    ●3.设置响应体
    ctx.response.body

    1. const path = require('path')
    2. const fileUtils = require('../utils/file_utils')
    3. module.exports = async (ctx, next) => {
    4. // 根据url
    5. const url = ctx.request.url // /api/seller ../data/seller.json
    6. let filePath = url.replace('/api', '') // /seller
    7. filePath = '../data' + filePath + '.json' // ../data/seller.json
    8. filePath = path.join(__dirname, filePath)
    9. try {
    10. const ret = await fileUtils.getFileJsonData(filePath)
    11. ctx.response.body = ret
    12. } catch (error) {
    13. const errorMsg = {
    14. message: '读取文件内容失败, 文件资源不存在',
    15. status: 404
    16. }
    17. ctx.response.body = JSON.stringify(errorMsg)
    18. }
    19. console.log(filePath)
    20. await next()
    21. }
    1. /utils下的file_utils.js文件*/
    2. // 读取文件的工具方法
    3. const fs = require('fs')
    4. module.exports.getFileJsonData = (filePath) => {
    5. // 根据文件的路径, 读取文件的内容
    6. return new Promise((resolve, reject) => {
    7. fs.readFile(filePath, 'utf-8', (error, data) => {
    8. if(error) {
    9. // 读取文件失败
    10. reject(error)
    11. } else {
    12. // 读取文件成功
    13. resolve(data)
    14. }
    15. })
    16. })
    17. }

    (5)跨域配置

    1.实际是通过Ajax访问服务器
    2.同源策略
    同协议\同域名\同端口
    当前页面的地址和Ajax获取数据的地址
    3.设置响应头

    1. async(ctx,next)=>{
    2. ctx.set("Access-Control-Allow-Origin", "*")
    3. ctx.set("Access-Control-Allow-Methods", "OPTIONS, GET, PUT, POST, DELETE")
    4. await next()
    5. }

    三  WebSocket的使用

    ●安装Websocket包

    npm i ws -S

    ●创建WebSocket实例对象

    1. const WebSocket = require("ws ")
    2. //创建出WebSocket实例对象
    3. const wss= new WebSocket. Server({
    4. port: 9998
    5. })

    监听事件

    1. wss.on("connection",client => {
    2. console.log("有客户端连接...")
    3. client. on ("message", msg => {
    4. console.log("客户端发送数据过来了")
    5. // 发送数据给客户 端
    6. client.send('hello socket ')
    7. })
    8. })

    测试代码如下:

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
    7. <title>Document</title>
    8. </head>
    9. <body>
    10. <button id="connect">连接</button>
    11. <button id="send" disabled="true">发送数据</button> <br>
    12. 从服务器接收的数据如下:<br>
    13. <span id="content"></span>
    14. <script>
    15. var connect = document.querySelector('#connect')
    16. var send = document.querySelector('#send')
    17. var content = document.querySelector('#content')
    18. var ws = null
    19. connect.onclick = function() {
    20. ws = new WebSocket('ws://localhost:9998')
    21. ws.onopen = () => {
    22. console.log('连接服务器成功')
    23. send.disabled = false
    24. }
    25. ws.onmessage = msg => {
    26. console.log('从服务器接收到了数据')
    27. content.innerHTML = msg.data
    28. }
    29. ws.onclose = e => {
    30. console.log('服务器关闭了连接')
    31. send.disabled = true
    32. }
    33. }
    34. send.onclick = function(){
    35. ws.send('hello websocket from frontend')
    36. }
    37. </script>
    38. </body>
    39. </html>

    四 改造后端程序

    ●1.创建service\web_ socket_ service.js文件

    1. const WebSocket = require("ws")
    2. // 创建出WebSocket实例对象
    3. const wss = new WebSocket.Server({
    4. port: 9998
    5. })
    6. module.exports.listen = function() {
    7. wss.on("connection", ws => {
    8. console.log("有客户端连接...")
    9. ws.on("message", msg => {
    10. console.log("客户端发送数据过来了")
    11. })
    12. })
    13. }

    ●2.在app.js中引入web_ socket_ service.js 这个文件,并调用listen方法

    1. const webSocketService = require('./service/web_ socket_ _service')
    2. webSocketService.listen()

    ●3.约定好和客户端之 间数据交互的格式和含义
          客户端和服务端之间的数据交互采用JSON格式
        客户端发送数据给服务端的字段如下:

    1. {
    2. "action": "getData",
    3. "socketType": "trendData",
    4. "chartName": "trend",
    5. "value": ""
    6. }

    或者 

    1. {
    2. "action": "fullScreen"
    3. "socketType": "fullScreen"
    4. "chartName": "trend"
    5. "value": true
    6. }

    或者 

    1. {
    2. ! action": "themeChange
    3. "socketType": "themeChange"
    4. "chartName": ""
    5. "value": "chalk"
    6. }

    其中:
    action:代表某项行为,可选值有
              ■getData 代表获取图表数据
              ■fullscreen代表产生了全屏事件
              ■themeChange 代表产生了主题切换的事件
    ■socketType:代表业务模块类型,这个值代表前端注册数据回调函数的标识,可选值有
            ■trendData
            ■sellerData
            ■ mapData
           ■rankData
            ■hotData
           ■ stockData
           ■ fullscreen
           ■themeChange

      ■chartName :代表图表名称,如果是主题切换事件,可不传此值,可选值有:
          ■ trend
          ■seller
         ■map
          ■ rank
          ■hot
          ■stock 
    ■value:代表具体的数据值,在获取图表数据时,可不传此值,可选值有
    ■如果是全屏事件, true代表全屏, false代表非全屏
    ■如果是主题切换事件,可选值有chalk或者vintage
    服务端发送给客户端的数据如下,

    1. {
    2. "action": "getData",
    3. "socketType": "trendData",
    4. "chartName": "trend",
    5. "value": "",
    6. "data": "从文件读取出来的json文件的内容"
    7. }
    8. 或者
    9. {
    10. "action": "fullScreen",
    11. "socketType": "fullScreen",
    12. "chartName": "trend",
    13. "value": true
    14. }
    15. 或者
    16. {
    17. "action": "themeChange",
    18. "socketType": "themeChange",
    19. "chartName": "",
    20. "value": "chalk"
    21. }

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

    1. const path = require('path')
    2. const fileUtils = require('../utils/file_utils')
    3. const WebSocket = require("ws")
    4. // 创建出WebSocket实例对象
    5. const wss = new WebSocket.Server({
    6. port: 9998
    7. })
    8. module.exports.listen = function() {
    9. wss.on("connection", client => {
    10. console.log("有客户端连接...")
    11. client.on("message", async msg => {
    12. let payload = JSON.parse(msg)
    13. if (payload.action === 'getData') {
    14. // 返回每个模块的数据
    15. let filePath = '../data/' + payload.chartName + '.json' //
    16. ../data/seller.json
    17. filePath = path.join(__dirname, filePath)
    18. const ret = await fileUtils.getFileJsonData(filePath)
    19. payload.data = ret // 增加data字段
    20. client.send(JSON.stringify(payload))
    21. } else {
    22. // 主题切换, 全屏切换, 进行每个客户端的同步, 收到什么数据就发送什么数据
    23. wss.clients.forEach(client => {
    24. console.log("*****************************************")
    25. client.send(message)
    26. })
    27. }
    28. })
    29. })
    30. }

  • 相关阅读:
    线性变换及其基本性质
    C++中的模板类pair
    利用正则表达式进行爬取数据以及正则表达式的一些使用方法
    HTML 脚本
    动态库静态库对比
    【计算机网络系列】概述:计算机网络体系结构与参考模型
    Bash脚本基础
    通过docker快速部署RabbitMq
    Canvas系列绘制图片学习:绘制图片和渐变效果
    Nuxt3项目如何通过开启ssr让网页实现seo自由!
  • 原文地址:https://blog.csdn.net/qq_62401904/article/details/126595883