写了个小程序,分享到掘金微信群,然后就被踢了的故事

声明

本着技术为大的态度分享此文,仅仅作为技术分享,无任何引流和违规内容,请草率观看。

事情起因

在工作水群之余,看到某微信群里分享了一个小程序,一个可以调用手机马达让手机震动,可以设置震动节奏。到这里大家应该知道是什么类型的小程序了。(此处有狗头)

然后我在群里说了句,单机版有什么意思?

群友A:"别逼逼,那你出个联机版,出了算你赢。"

我:"好"。

男人这该死的胜负欲。

开发过程

注册/认证/备案小程序

注册流程不用说了,很简单。只是我这没有邮箱了,于是用了自己的域名绑定的腾讯企业邮箱搞定。

认证的话,个人认证 ¥30.00/年,企业是 ¥300.00/年。因为我啥接口和权限都不需要,就用了个人。

备案比较糟糕,填了资料,等了五天左右才下来。

开始开发

首先得来个 WebSocket服务端,那就 NodeJS 吧。

javascript 复制代码
console.log("\n**********************************");
const WSS_PORT = 10102;
const REDIS_PORT = 6379;
const REDIS_HOST = "127.0.0.1";
const websocket = require("nodejs-websocket");
const redis = require("ioredis");
const TOPIC_PREFIX = "topic_";
async function init() {
  const webSocketServer = await websocket.createServer(async conn => {
    console.log("[debug]\t\tConnection ready");
    const redisSub = redis.createClient();
    const redisPub = redis.createClient();
    redisSub.subscribe("all");
    redisSub.on("message", (channel, message) => {
      console.log("channel,message", channel, message);
      if (conn.readyState === 1) {
        conn.send(message);
      }
    });
    conn.on("text", async msg => {
      console.log("[message]\t\t" + msg);
      switch (msg) {
        case "ping":
          conn.send('pong');
          break;
        case "bye":
          conn.send("bye");
          conn.close();
          break;
        default:
          try {
            const obj = JSON.parse(msg);
            switch (obj.type) {
              case "join":
                console.log("join " + obj.topic);
                redisSub.subscribe(TOPIC_PREFIX + obj.topic);
                break;
              case "active":
                try {
                  redisPub.publish(TOPIC_PREFIX + obj.topic, JSON.stringify({
                      type:"active",
                      msg: obj.msg
                  }));
                } catch (e) {
                  console.error("发布失败");
                }
                break;
              case "leave":
                console.log("leave " + obj.topic);
                redisSub.unsubscribe(TOPIC_PREFIX + obj.topic);
                break;
              case "touch":
                try {
                  redisPub.publish(TOPIC_PREFIX + obj.topic, "touch");
                } catch (e) {
                  console.error("发布失败");
                }
                break;
              default:
                console.log("unknown command: ".obj.type);
            }
          } catch (e) {
            console.error(e);
          }
      }
    });
    conn.on("close", () => {
      redisSub.quit();
    });
    conn.on("error", () => {});
  });
  webSocketServer.listen(WSS_PORT);
  console.log("BBBUG Websocket Service Running : (" + WSS_PORT + ")");
}
init();

代码放出来了,因为做的仓促,没有加权限验证什么的,数据结构也是随心搞了搞,强迫症可以跳过代码质量这一趴。

客户端的话,我本来用的 TypeScript 写的小程序,但后来好像没什么需求,删了其他的文件之后,TypeScript 的优势一点都没体现出来。

代码如下:

typescript 复制代码
const websocketUrl = "wss://hamm.cn/"
const apiUrl = "https://hamm.cn/"
Page({
  data: {
    shake: "",
    isShaking: false,
    isTouching: false,
    ticket: "",
    connected: false,
    currentMessage: "",
    messageList: [],
    timerShake: -1,
    timerShowMessage: -1,
    timerMessageStop: -1,
    timerHeartBeat: -1,
    websocket: wx.connectSocket({
      url: websocketUrl
    }),
  },
  onLoad(option: any) {
    let ticket = wx.getStorageSync("channel") || ""
    if (option && option.ticket) {
      ticket = option.ticket
    }
    this.setTicket(ticket)

    const updateManager = wx.getUpdateManager()

    updateManager.onCheckForUpdate(() => { })

    updateManager.onUpdateReady(() => {
      wx.showModal({
        title: '更新提示',
        content: '新版本已经准备好,是否重启应用?',
        success: (res) => {
          if (res.confirm) {
            updateManager.applyUpdate()
          }
        }
      })
    })
    updateManager.onUpdateFailed(function () {
    })
  },
  getMessageList() {
    wx.request({
      url: apiUrl + "getMessageList",
      success: (res) => {
        const json = res.data as Record<string, any>
        this.setData({
          messageList: json.data
        })
      }
    })
  },
  onShow() {
    this.connect()
  },
  startHeartBeat() {
    clearTimeout(this.data.timerHeartBeat)
    console.log("心跳");
    this.sendMessage("ping")
    this.data.timerHeartBeat = setTimeout(() => {
      this.startHeartBeat()
    }, 10000);
  },
  sendMessage(res: string) {
    try {
      this.data.websocket.send({
        data: res
      })
    } finally {
    }
  },
  onShareAppMessage() {
    return {
      title: '快来一起震一下呀~',
      path: '/view/index/index?ticket=' + this.data.ticket
    }
  },
  joinChannel() {
    wx.showModal({
      title: "加入频道",
      editable: true,
      confirmText: "加入",
      placeholderText: "请输入6位频道ID...",
      success: (res) => {
        if (res.confirm) {
          if (!/^\d{6}$/.test(res.content)) {
            wx.showModal({
              title: "格式错误",
              content: "请输入六位数字频道ID",
              confirmText: "重新输入",
              success: (res) => {
                if (res.confirm) {
                  this.joinChannel();
                }
              }
            })
            return;
          }
          wx.showModal({
            title: "加入频道",
            content: "加入频道 " + res.content + " 成功!",
            showCancel: false
          })
          this.setTicket(res.content)
          this.getMessageList()
          this.sendMessage(JSON.stringify({
            type: "join",
            topic: this.data.ticket
          }))
        }
      }
    })
  },
  stopShake() {
    this.data.isShaking = false
    this.setData({
      shake: "."
    })
  },
  exitChannel() {
    wx.showModal({
      title: "退出频道",
      content: "是否确认退出频道 " + this.data.ticket,
      confirmText: "退出频道",
      confirmColor: "#f00",
      success: (res) => {
        if (res.confirm) {
          this.stopShake()
          this.sendMessage(JSON.stringify({
            type: "leave",
            topic: this.data.ticket
          }))
          this.setTicket("")
        }
      }
    })
  },
  setTicket(ticket: string) {
    this.setData({
      ticket: ticket
    })
    wx.setStorageSync("channel", ticket)
  },
  connect() {
    this.data.websocket.onOpen(() => {
      this.data.connected = true
      wx.showToast({
        title: "连接成功",
        icon: "success"
      })
      if (this.data.ticket) {
        this.sendMessage(JSON.stringify({
          type: "join",
          topic: this.data.ticket
        }))
      }
      this.startHeartBeat()
    });
    this.data.websocket.onMessage((res) => {
      switch (res.data) {
        case "pong":
          break;
        case "touch":
          if (this.data.isTouching) {
            return
          }
          this.startShake()
          clearTimeout(this.data.timerMessageStop)
          this.data.timerMessageStop = setTimeout(() => {
            this.stopShake()
          }, 500)
          break;
        default:
          try {
            const json = JSON.parse(res.data.toString());
            switch (json.type) {
              case 'active':
                this.setData({
                  currentMessage: json.msg || ""
                })
                clearTimeout(this.data.timerShowMessage)
                this.data.timerShowMessage = setTimeout(() => {
                  this.setData({
                    currentMessage: ""
                  })
                }, 3000)
                break;
              default:
            }
          } catch (e: any) {
            console.log(e);
          }
      }
    })
    this.data.websocket.onClose(() => {
      clearTimeout(this.data.timerHeartBeat)
      this.data.connected = false
      wx.showToast({
        title: "连接断开",
        icon: "error"
      })
      this.data.websocket = wx.connectSocket({
        url: websocketUrl
      })
    })
  },
  createConnection() {
    wx.showToast({
      title: "连接中",
      icon: "loading"
    })
    this.connect()
  },
  publish() {
    if (this.data.ticket && this.data.isTouching) {
      this.sendMessage(JSON.stringify({
        type: "touch",
        topic: this.data.ticket
      }))
      console.log("touch");
    }
  },
  touchStart() {
    console.log("开始震动")
    this.data.isTouching = true;
    this.startShake()
  },
  startShake() {
    if (!this.data.isShaking) {
      this.data.isShaking = true
      this.setData({
        shake: "shake"
      })
      this.shake()
    }
  },
  touchStop() {
    this.data.isTouching = false
    this.stopShake();
    this.setData({
      shake: "."
    })
    console.log("停止震动")
  },
  shake() {
    if (!this.data.isShaking) {
      return
    }
    console.log("...");
    this.publish()
    wx.vibrateShort({
      type: "heavy"
    })
    setTimeout(() => {
      wx.vibrateLong()
      setTimeout(() => {
        wx.vibrateShort({
          type: "heavy"
        })
        this.data.timerShake = setTimeout(() => {
          this.shake()
        }, 100)
      }, 410)
    }, 30)
  },
  fastMessage() {
    wx.showActionSheet({
      itemList: this.data.messageList,
      success: (res) => {
        this.sendMessage(JSON.stringify({
          type: "active",
          topic: this.data.ticket,
          msg: this.data.messageList[res.tapIndex]
        }))
      }
    })
  },
})

如上,完成了 单机版 + 独立频道联机版。就这么发布吧。

然后就分享到了一些微信群,其中就有 掘金前端交流群,然后就被踢了哈哈哈哈哈哈哈哈哈哈哈哈。

后续

可能会跟一些支持蓝牙的 硬件 互动一下(手动狗头),有兴趣的朋友可以继续关注我后续的文。

最后

可以搜索一下 震当时 体验一下,本文只是做一个开发趣事分享,就不贴二维码引流了。

就酱。

相关推荐
JELEE.1 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl3 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫4 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友4 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理6 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻6 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js
mapbar_front7 小时前
在职场生存中如何做个不好惹的人
前端
牧杉-惊蛰7 小时前
纯flex布局来写瀑布流
前端·javascript·css
一袋米扛几楼988 小时前
【软件安全】什么是XSS(Cross-Site Scripting,跨站脚本)?
前端·安全·xss
向上的车轮9 小时前
Actix Web适合什么类型的Web应用?可以部署 Java 或 .NET 的应用程序?
java·前端·rust·.net