像 Redux 一样封装一个 websocket January 19, 2020 / 2 min read dev , javascript const WS_URL = 'ws://demo.com/ws'export class WSConnection { constructor(liveId) { this.connection = new WebSocket(WS_URL) this.connected = false this.listeners = [] this.connection.onopen = () => { console.log('[ws] connection established!') this.connected = true this.connection.send("HEATBEAT") } this.connection.onmessage = e => { // console.log('[ws] receive:', e.data) this.listeners.forEach(listener => listener(e)) } this.connection.onerror = e => { this.connected = false console.log('[ws] error:', e.message) } this.connection.onclose = e => { this.connected = false console.log('[ws] close:', e.code, e.reason) } } stop() { if (this.connected) { this.listeners = [] this.connection.close() } } send(msg) { if (this.connected) { this.connection.send(msg) console.log('[ws] send message:', msg) } } listen(listener) { this.listeners.push(listener) return () => { this.listeners = this.listeners.filter(l => l !== listener) } }} 将 websocket 封装一下, 比较符合 OO 的哲学, 并且可以达到与业务代码抽离的好处, 在业务代码中使用: class extends React.Component { connection = new WSConnection('DEMO_ID') componentDidMount() { this.connection.listen(this.handleMessage) } componentWillUnmount() { this.connection.stop() } handleMessage = e => { // TODO } handleSendBarrage = message => { // construct a string action this.connection.send(barrageAction(message)) }} 这里对 WSConnection 的封装, 是借鉴 Redux 核心代码: function createStore(reducer) { let state = null let listeners = [] const getState = () => state const subscribe = listener => { listeners.push(listener) return () => { listeners = listeners.filter(l => l !== listener) } } const dispatch = action => { state = reducer(state, action) listeners.forEach(listener => listener()) } dispatch(null) return { getState, dispatch, subscribe }} 这里的 subscribe 和 dispatch 与封装的 listen 和 send 是不是很像呢.