-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
97 lines (90 loc) · 2.74 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
* Storeon is a module to sync events through WebSocket
* @param {String} url Address of WebSocket server
* @param {Object} [options] Module configuration
* @param {String[]} [options.include] List of events to sync
* @param {String[]} [options.exclude] List of events to ignore
* @param {Number} [options.reconnectInterval] Time (ms) to reconnect
* @param {Number} [options.pingPongInterval] Interval (ms) to ping server
**/
let websocket = function (url, options) {
options = options || {}
let include = options.include
let exclude = options.exclude
let reconnectInterval = options.reconnectInterval || 500
let pingPongInterval = options.pingPongInterval || 2000
if (process.env.NODE_ENV === 'development') {
if (!url) {
throw new Error(
'The url parameter should be a string. ' +
'For example: "ws://localhost:8080"'
)
}
}
return function (store) {
let connection
let reconnectTimer
let pingPongTimer
let pingPongAttempt = false
let reconnectAttempt = false
let fromWS = Symbol('ws')
function reconnect () {
if (reconnectAttempt) return
clearTimeout(reconnectTimer)
reconnectAttempt = true
reconnectTimer = setTimeout(() => {
start()
}, reconnectInterval)
}
function message (event) {
if (event.data === 'pong') {
pingPongAttempt = false
return
}
try {
let receive = JSON.parse(event.data)
receive.value = receive.value || {}
if (include && !include.includes(receive.event)) return
if (exclude && exclude.includes(receive.event)) return
receive.value[fromWS] = true
store.dispatch(receive.event, receive.value)
} catch (e) {}
}
function pingPong () {
if (!pingPongAttempt) {
connection.send('ping')
} else {
start()
}
pingPongAttempt = !pingPongAttempt
}
function start () {
clearInterval(pingPongTimer)
clearTimeout(reconnectTimer)
connection = new WebSocket(url)
connection.addEventListener('close', reconnect)
connection.addEventListener('error', reconnect)
connection.addEventListener('message', message)
pingPongTimer = setInterval(pingPong, pingPongInterval)
}
start()
store.on('@dispatch', (_, data) => {
if (
(data[0] && data[0][0] === '@') ||
(data[1] && data[1][fromWS]) ||
connection.readyState !== WebSocket.OPEN ||
(include && !include.includes(data[0])) ||
(exclude && exclude.includes(data[0]))
) {
return
}
connection.send(
JSON.stringify({
event: data[0],
value: data[1]
})
)
})
}
}
module.exports = { websocket }