Skip to content
This repository was archived by the owner on Apr 15, 2023. It is now read-only.

Commit 848aaac

Browse files
authored
Merge pull request #21 from jlkalberer/master
Update EventSource to support chunked data
2 parents df73ef5 + 174541d commit 848aaac

1 file changed

Lines changed: 56 additions & 40 deletions

File tree

EventSource.js

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66

77
var reTrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
88

9-
var EventSource = function (url, options) {
9+
var EventSource = function(url, options) {
1010
var eventsource = this,
11-
interval = 500, // polling interval
12-
lastEventId = null,
13-
cache = '',
14-
eventType;
11+
interval = 500, // polling interval
12+
lastEventId = null,
13+
lastIndexProcessed = 0,
14+
eventType;
1515

1616
if (!url || typeof url != 'string') {
1717
throw new SyntaxError('Not enough arguments');
@@ -24,13 +24,14 @@ var EventSource = function (url, options) {
2424
this._xhr = null;
2525

2626
function pollAgain(interval) {
27-
eventsource._pollTimer = setTimeout(function () {
27+
eventsource._pollTimer = setTimeout(function() {
2828
poll.call(eventsource);
2929
}, interval);
3030
}
3131

3232
function poll() {
33-
try { // force hiding of the error message... insane?
33+
try {
34+
// force hiding of the error message... insane?
3435
if (eventsource.readyState == eventsource.CLOSED) return;
3536

3637
// NOTE: IE7 and upwards support
@@ -47,15 +48,20 @@ var EventSource = function (url, options) {
4748
// readychange until the server connection is closed
4849
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
4950

50-
if (lastEventId != null) xhr.setRequestHeader('Last-Event-ID', lastEventId);
51-
cache = '';
51+
if (lastEventId != null)
52+
xhr.setRequestHeader('Last-Event-ID', lastEventId);
53+
lastIndexProcessed = 0;
5254

53-
xhr.timeout = (this.OPTIONS && this.OPTIONS.timeout !== undefined)
55+
xhr.timeout =
56+
this.OPTIONS && this.OPTIONS.timeout !== undefined
5457
? this.OPTIONS.timeout
55-
: 50000
58+
: 50000;
5659

57-
xhr.onreadystatechange = function () {
58-
if (this.readyState == 3 || (this.readyState == 4 && this.status == 200)) {
60+
xhr.onreadystatechange = function() {
61+
if (
62+
this.readyState == 3 ||
63+
(this.readyState == 4 && this.status == 200)
64+
) {
5965
// on success
6066
if (eventsource.readyState == eventsource.CONNECTING) {
6167
eventsource.readyState = eventsource.OPEN;
@@ -68,13 +74,12 @@ var EventSource = function (url, options) {
6874
} catch (e) {}
6975

7076
// process this.responseText
71-
var parts = responseText.substr(cache.length).split("\n"),
72-
data = [],
73-
i = 0,
74-
retry = 0,
75-
line = '';
76-
77-
cache = responseText;
77+
var parts = responseText.substr(lastIndexProcessed).split('\n'),
78+
data = [],
79+
i = 0,
80+
retry = 0,
81+
line = '';
82+
lastIndexProcessed = responseText.lastIndexOf('\n\n') + 2;
7883

7984
// TODO handle 'event' (for buffer name), retry
8085
for (; i < parts.length; i++) {
@@ -83,16 +88,23 @@ var EventSource = function (url, options) {
8388
eventType = line.replace(/event:?\s*/, '');
8489
} else if (line.indexOf('retry') == 0) {
8590
retry = parseInt(line.replace(/retry:?\s*/, ''));
86-
if(!isNaN(retry)) { interval = retry; }
91+
if (!isNaN(retry)) {
92+
interval = retry;
93+
}
8794
} else if (line.indexOf('data') == 0) {
8895
data.push(line.replace(/data:?\s*/, ''));
8996
} else if (line.indexOf('id:') == 0) {
9097
lastEventId = line.replace(/id:?\s*/, '');
91-
} else if (line.indexOf('id') == 0) { // this resets the id
98+
} else if (line.indexOf('id') == 0) {
99+
// this resets the id
92100
lastEventId = null;
93101
} else if (line == '') {
94102
if (data.length) {
95-
var event = new MessageEvent(data.join('\n'), eventsource.url, lastEventId);
103+
var event = new MessageEvent(
104+
data.join('\n'),
105+
eventsource.url,
106+
lastEventId,
107+
);
96108
eventsource.dispatchEvent(eventType || 'message', event);
97109
data = [];
98110
eventType = undefined;
@@ -102,11 +114,13 @@ var EventSource = function (url, options) {
102114

103115
if (this.readyState == 4) pollAgain(interval);
104116

105-
// don't need to poll again, because we're long-loading
117+
// don't need to poll again, because we're long-loading
106118
} else if (eventsource.readyState !== eventsource.CLOSED) {
107-
if (this.readyState == 4) { // and some other status
119+
if (this.readyState == 4) {
120+
// and some other status
108121
pollAgain(interval);
109-
} else if (this.readyState == 0) { // likely aborted
122+
} else if (this.readyState == 0) {
123+
// likely aborted
110124
pollAgain(interval);
111125
}
112126
}
@@ -116,9 +130,11 @@ var EventSource = function (url, options) {
116130
// dispatch error
117131
eventsource.readyState = eventsource.CONNECTING;
118132

119-
eventsource.dispatchEvent('error',
120-
{ type: 'error', message: this.responseText });
121-
}
133+
eventsource.dispatchEvent('error', {
134+
type: 'error',
135+
message: this.responseText,
136+
});
137+
};
122138

123139
if (eventsource.OPTIONS.body) {
124140
xhr.send(eventsource.OPTIONS.body);
@@ -127,23 +143,23 @@ var EventSource = function (url, options) {
127143
}
128144

129145
if (xhr.timeout > 0) {
130-
setTimeout(function () {
146+
setTimeout(function() {
131147
if (true || xhr.readyState == 3) xhr.abort();
132148
}, xhr.timeout);
133149
}
134150

135151
eventsource._xhr = xhr;
136-
137-
} catch (e) { // in an attempt to silence the errors
152+
} catch (e) {
153+
// in an attempt to silence the errors
138154
eventsource.dispatchEvent('error', { type: 'error', data: e.message }); // ???
139155
}
140-
};
156+
}
141157

142158
poll(); // init now
143159
};
144160

145161
EventSource.prototype = {
146-
close: function () {
162+
close: function() {
147163
// closes the connection - disabling the polling
148164
this.readyState = this.CLOSED;
149165
clearInterval(this._pollTimer);
@@ -152,7 +168,7 @@ EventSource.prototype = {
152168
CONNECTING: 0,
153169
OPEN: 1,
154170
CLOSED: 2,
155-
dispatchEvent: function (type, event) {
171+
dispatchEvent: function(type, event) {
156172
var handlers = this['_' + type + 'Handlers'];
157173
if (handlers) {
158174
for (var i = 0; i < handlers.length; i++) {
@@ -164,14 +180,14 @@ EventSource.prototype = {
164180
this['on' + type].call(this, event);
165181
}
166182
},
167-
addEventListener: function (type, handler) {
183+
addEventListener: function(type, handler) {
168184
if (!this['_' + type + 'Handlers']) {
169185
this['_' + type + 'Handlers'] = [];
170186
}
171187

172188
this['_' + type + 'Handlers'].push(handler);
173189
},
174-
removeEventListener: function (type, handler) {
190+
removeEventListener: function(type, handler) {
175191
var handlers = this['_' + type + 'Handlers'];
176192
if (!handlers) {
177193
return;
@@ -187,10 +203,10 @@ EventSource.prototype = {
187203
onmessage: null,
188204
onopen: null,
189205
readyState: 0,
190-
URL: ''
206+
URL: '',
191207
};
192208

193-
var MessageEvent = function (data, origin, lastEventId) {
209+
var MessageEvent = function(data, origin, lastEventId) {
194210
this.data = data;
195211
this.origin = origin;
196212
this.lastEventId = lastEventId || '';
@@ -200,7 +216,7 @@ MessageEvent.prototype = {
200216
data: null,
201217
type: 'message',
202218
lastEventId: '',
203-
origin: ''
219+
origin: '',
204220
};
205221

206222
export default EventSource;

0 commit comments

Comments
 (0)