nodejs服务+koa+socket.io前后端搭建预研

20 篇文章 0 订阅
4 篇文章 0 订阅

服务入口文件

// IOT服务
const iot = require("./iot/runtime");
const iotInstance = new iot(require("./config").runMode, 2000); //production or development
iotInstance.run();

// koa服务
const Koa = require("koa");
const app = new Koa();

// 解决跨域问题
const cors = require("./utils/cors");
app.use(cors);

// 通过koa内部封装好的上下文进行判断处理get、post、html页面
app.use(async (ctx: any, next: any) => {
  const { url, method } = ctx;
  console.log(666.999, url, method);
  // 前端调用示例:const value = await axios.post('http://127.0.0.1:9098/users');
  const getLists = ["/get", "/user/get", "/users"];
  const postLists = ["/post", "/user/post", "/users"];
  if (url.startsWith("/socket")) {
    console.log(666.456, "进入ws通信", url, method);
    await next();
  } else if (method === "GET" && getLists.includes(url)) {
    // 当GET请求时候的处理
    ctx.body = "get test" + url;
  } else if (method === "POST" && postLists.includes(url)) {
    // post请求的处理
    ctx.body = "post test" + url;
  } else {
    // 除了以上的数据特殊处理请求外,均执行dist文件包to网站服务
    const path = require("path");
    // 加载html页面或ejs、pug模板等
    const Views = require("koa-views");
    app.use(
      Views(path.join(__dirname, "../web-client-dist/ui"), {
        extension: "html",
        // map: { html: "html" },
      })
    );
    // 静态资源加载
    const Static = require("koa-static");
    app.use(Static(path.join(__dirname, "../web-client-dist/ui")));

    // 继续执行接下来的服务*必须
    await next();
  }
});

// nodejs启动http服务
const http = require("http");
const server = http.createServer(app.callback());

// websocket服务
const Socket = require("socket.io");
const io = Socket(server, {
  allowEIO3: true,
  // cors: true,
  cors: {
    origin: "*", // WS跨域,DEV调试的时候需要,示例:http://localhost:909
    methods: ["GET", "POST"],
  },
});
const sockets: any[] = [];
io.on("connection", (socket: any) => {
  console.log("socket conncet,id is:", socket.id);
  sockets.push(socket);

  socket.on("msg-client", (msg: string) => {
    console.log("client msg:", msg);
    socket.emit("msg-server", { msg: msg }, (res: any) => {
      console.log(666.329, res);
    });
  });

  socket
    .timeout(5000)
    .emit("timeout", "hello world", (err: any, response: any) => {
      if (err) {
        // 另一方未在给定延迟内确认事件
      } else {
        console.log(response); // "got it"
      }
    });

  socket.on("disconnect", () => {
    console.log("user disconnected" + socket.id);
  });
});

io.on("disconnect", () => {
  console.log("disconnect");
});

let indexNum: number = 1;
setInterval(() => {
  indexNum++;
  io.emit("msg", iotInstance.Model);
  io.emit("msg-index", indexNum);
  // console.log(
  //   sockets.map((item) => {
  //     return {
  //       id: item.id,
  //       connect_status: item.connected,
  //     };
  //   })
  // );
}, 1000);

//nodejs服务启动,包含http及ws
const { APP_PORT } = require("./config/config.default");
server.listen(APP_PORT, function () {
  console.log("server is running on http://127.0.0.1:" + APP_PORT);
});

跨域封装文件

// const REG_WHITE_LIST = /^https?:\/\/(?:[0-9a-zA-Z-]+\.)*\.(?:ws|biz|com)(?::\d+)?$/;// 正则方式匹配 REG_WHITE_LIST.test(origin)
const REG_WHITE_LIST = ["http://127.0.0.1:909", "http://127.0.0.1:9098"];
// 这里写上想要匹配的域名
module.exports = async (ctx: any, next: any) => {
  const origin = ctx.request.header.origin;
  // const origin = ctx.get("Origin");
  console.log(
    666.789,
    Date.now(),
    ctx.request.header.origin,
    REG_WHITE_LIST.includes(origin)
  );
  if (origin && REG_WHITE_LIST.includes(origin)) {
    ctx.set("Access-Control-Allow-Origin", origin); // 允许跨域
    ctx.set("Access-Control-Allow-Methods", "POST,GET,OPTIONS,HEAD,PUT,DELETE"); // 支持的方法
    ctx.set("Access-Control-Allow-Credentials", "true"); // 允许传入Cookie
    ctx.set("Access-Control-Max-Age", 2592000); // 过期时间一个月
    // 如果有特殊的请求头,直接响应
    if (ctx.get("Access-Control-Request-Headers")) {
      ctx.set(
        "Access-Control-Allow-Headers",
        ctx.get("Access-Control-Request-Headers")
      );
    }
    // FIX:浏览器某些情况下没有带Origin头
    ctx.set("Vary", "Origin");
    // 如果是 OPTIONS 请求,则直接返回
    if (ctx.method === "OPTIONS") {
      ctx.status = 204;
      return;
    }
  }
  await next();
};

socket.io客户端示例

<script setup lang="ts">
import opt1 from './charts/multipleLines';
import * as echarts from 'echarts';

import { getCurrentInstance, onMounted, reactive, ref } from 'vue';
import axios from 'axios';

import { io } from 'socket.io-client';
const socket = io('ws://127.0.0.1:9098');
const data1 = reactive({
  time: ['1', '2'],
  voltage: [380, 370],
  current: [100, 110],
});
const indexstr = ref('');
const data2: any[] = reactive([]);
const panel = ref();
const $echarts = echarts;

const ioServerCount = ref(1);
const ioServerMsg = ref('');

function sendMsg(msg: string) {
  ioServerCount.value++;
  console.log(666.333, ioServerCount.value + ': ' + msg);
  socket.emit('msg-client', ioServerCount.value + ': ' + msg);
}

onMounted(() => {
  const myChart1 = $echarts.init(panel.value);
  myChart1.setOption(opt1(data1));

  socket.on('connect', () => {
    console.log('connect');
  });

  socket.on('msg-server', (msg: { msg: string }, callback) => {
    ioServerMsg.value = msg.msg;
    callback('got it');
  });

  socket.on('msg-index', (msg: string) => {
    indexstr.value = msg;
  });

  socket.on('msg', (data: any) => {
    data1.time.push(data.voltage.update);
    data1.voltage.push(data.voltage.value);
    data1.current.push(data.current.value);

    if (data1.time.length > 5) {
      data1.time.shift();
      data1.voltage.shift();
      data1.current.shift();
    }

    myChart1.setOption(opt1(data1));

    data2.push(data);
    if (data2.length > 5) {
      data2.shift();
    }
  });
});

const apimsg = ref('');
async function apiMsg(type: number) {
  // apimsg.value = await axios.get('http://127.0.0.1:3333/page/helloworld');
  // apimsg.value = await axios.get('http://127.0.0.1:3333/users/login');
  if (type === 1) {
    apimsg.value = await axios.get('http://127.0.0.1:9098/users');
  } else if (type === 2) {
    apimsg.value = await axios.post('http://127.0.0.1:9098/users');
  } else if (type === 3) {
    apimsg.value = await axios.post('http://127.0.0.1:9098/socket.io');
  } else if (type === 4) {
    apimsg.value = await axios.post('http://127.0.0.1:9098/');
  }
}
</script>

<template>
  <h1>Socket.IO预研{{ indexstr }}</h1>
  <el-button @click.stop="apiMsg(1)">API1</el-button>
  <el-button @click.stop="apiMsg(2)">API2</el-button>
  <el-button @click.stop="apiMsg(3)">API3</el-button>
  <el-button @click.stop="apiMsg(4)">API4</el-button>
  {{ apimsg }}
  <div class="dangger">aaa</div>
  <div class="bg">
    <div id="panel" ref="panel"></div>
    <div ref="panel2" id="panel2">
      <p v-for="(item, index) in data2" :key="index">
        <!-- {{item}} -->
        <span>{{ new Date(item.voltage.update) }}</span>
        {{ item.voltage.des }}:{{ item.voltage.value }}
        {{ item.current.des }}:{{ item.current.value }} {{ item.speed.des }}:{{
          item.speed.value
        }}
        <!-- {{item.voltage.des}}:{{item.voltage.value}} -->
      </p>
    </div>
  </div>
  ---123
  <div>
    <el-button @click.stop="sendMsg('发送消息1')" type="primary">
      发送消息1
    </el-button>
    <el-button @click.stop="sendMsg('test1')">test1</el-button>
    接收的服务器消息:{{ ioServerMsg }}
  </div>
</template>

<style scoped lang="scss">
.bg {
  background-color: bisque;
}
#panel {
  width: 400px;
  height: 300px;
}
#panel2 {
  width: 400px;
  height: 300px;
  p {
    display: block;
    border: solid 1px #003366;
    margin: 0;
    span {
      display: block;
    }
  }
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿赛工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值