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

声明

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

事情起因

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

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

群友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]
        }))
      }
    })
  },
})

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

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

后续

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

最后

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

就酱。

相关推荐
小小李程序员9 分钟前
css边框修饰
前端·css
我爱画页面41 分钟前
使用dom-to-image截图html区域为一张图
前端·html
忧郁的西红柿1 小时前
HTML-DOM模型
前端·javascript·html
bin91531 小时前
【油猴脚本】00010 案例 Tampermonkey油猴脚本,动态渲染表格-添加提示信息框,HTML+Css+JavaScript编写
前端·javascript·css·bootstrap·html·jquery
Stanford_11061 小时前
C++入门基础知识79(实例)——实例 4【求商及余数】
开发语言·前端·javascript·c++·微信小程序·twitter·微信开放平台
Good_Luck_Kevin20181 小时前
速通sass基础语法
前端·css·sass
大怪v2 小时前
前端恶趣味:我吸了juejin首页,好爽!
前端·javascript
反应热2 小时前
浏览器的本地存储技术:从 `localStorage` 到 `IndexedDB`
前端·javascript
刘杭2 小时前
在react项目中使用Umi:dva源码简析之redux-saga的封装
前端·javascript·react.js
pan_junbiao2 小时前
Vue使用axios二次封装、解决跨域问题
前端·javascript·vue.js