lukas-reining / eventsource Goto Github PK
View Code? Open in Web Editor NEWEventSource implementation that is fully compliant with the WHATWG Server-Sent Events specification but takes more arguments.
License: MIT License
EventSource implementation that is fully compliant with the WHATWG Server-Sent Events specification but takes more arguments.
License: MIT License
Hi, just letting you know that you're linking to a 404 LICENSE file in the readme: https://github.com/lukas-reining/eventsource/blob/main/LICENSE
When a working EventSource is failed (by the remote end closing the connection), reconnect() is called internally as expected.
reconnect() checks whether readyState has been set to CLOSED (it hasn't), and then queues a call to connect() after a timeout:
eventsource/src/eventsource.ts
Line 168 in 14c16b6
Before the timeout expires, the consuming application calls close(), which changes the readyState to CLOSED.
Once the timeout expires, connect() resets readyState to CONNECTING:
eventsource/src/eventsource.ts
Line 71 in 14c16b6
.. and the previously closed EventSource begins emitting messages.
A quick fix might be to test readyState early in connect() or to store the timeoutID returned by reconnect()'s setTimeout() and call clearTimeout() during close().
When setting disableRetry
to true
in the config and an event happens that would trigger a retry, the library still logs a warning to the console, although the retry will not happen due to the disableRetry
option in the config.
This is a bit confusing. The warning tells the developer it will reconnect to the event-source, while actually not doing so.
I think it should not log the warning in this case. Or is this expected behaviour?
Using "type": "module"
in package.json, results in the following behavior. Hers's a minimally viable example:
Node version 18.19.1
extended-eventsource@^1.4.6
import { EventSource } from 'extended-eventsource';
const es = new EventSource(<MY_SSE_URL>, {
withCredentials: true,
disableLogger: true,
});
es.onopen = () => {
console.log('EventSource connected');
};
node index.js
)import { EventSource } from 'extended-eventsource';
^^^^^^^^^^^
SyntaxError: Named export 'EventSource' not found. The requested module 'extended-eventsource' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'extended-eventsource';
const { EventSource } = pkg;
at ModuleJob._instantiate (node:internal/modules/esm/module_job:123:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:191:5)
at async ModuleLoader.import (node:internal/modules/esm/loader:336:24)
at async loadESM (node:internal/process/esm_loader:34:7)
Node.js v18.19.1dleMainPromise (node:internal/modules/run_main:106:12)
The suggested "fix" from the error no effect, and result in the following:
import pkg from 'extended-eventsource';
const { EventSource } = pkg;
const es = new EventSource('https://sdk.flagsync.com/events/sdk-updates', {
withCredentials: true,
disableLogger: true,
});
es.onopen = () => {
console.log('EventSource connected');
};
export { CustomEventSource, CustomEventSource as EventSource };
^^^^^^
SyntaxError: Unexpected token 'export'
at internalCompileFunction (node:internal/vm:73:18)
at wrapSafe (node:internal/modules/cjs/loader:1274:20)
at Module._compile (node:internal/modules/cjs/loader:1320:27)
{
"name": "modern",
"version": "1.0.0",
"description": "",
"main": "index",
"type": "module",
"scripts": {
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"extended-eventsource": "^1.4.6"
}
}
require
does work as expected; must remove "type": "module"
from package.json
const { EventSource } = require('extended-eventsource');
const es = new EventSource(<MY_SSE_URL>, {
withCredentials: true,
disableLogger: true,
});
es.onopen = () => {
console.log('EventSource connected');
};
EventSource connected
{
"name": "scripts",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"extended-eventsource": "^1.4.6"
}
}
The eventsource
repository currently lists core-js
as a dependency, but it seems to be unused throughout the codebase. I suggest removing this dependency to streamline the project.
Thanks for creating such a wonderful package, @lukas-reining
I was trying to use sse in my angular app, but couldn't set Authorization header for request, and I found this package, really helpful.
By the way, why does it send empty string "" as the first data?
Of course, this is not a big issue, but as I was trying to send json string from backend and parse it on frontend, I encountered this, which caught me for some time.
Of course I added validation logic to avoid error, but I just want this package to be perfect.
This is working fine on local development, when I run angular app on localhost:4200,
However, once I deploy the app to the vercel, it returns error.
main-6FYVCRR5.js:7 ERROR TypeError: (void 0) is not a constructor
at e.getEventSource (main-6FYVCRR5.js:18:4128)
at i._subscribe (main-6FYVCRR5.js:18:3856)
at i._trySubscribe (main-6FYVCRR5.js:3:4428)
at main-6FYVCRR5.js:3:4373
at Ua (main-6FYVCRR5.js:3:2222)
at i.subscribe (main-6FYVCRR5.js:3:4289)
at e.<anonymous> (main-6FYVCRR5.js:18:11341)
at Generator.next (<anonymous>)
at chunk-2WQGNY7Y.js:1:1640
at new t (polyfills-LZBJRJJE.js:2:2128)
this is the compiled source which I can see in devtools
getEventSource(t) {
return new (void 0)(t,{
headers: {
Authorization: "Bearer " + this.token
},
retry: 3e3
})
}
here's my source code
import { Injectable, NgZone, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { apiUrl } from '../../environment';
import { AuthRegularService } from '../services/auth-regular.service';
import { EventSource as CustomEventSource } from 'extended-eventsource';
@Injectable({
providedIn: 'root',
})
export class SseService {
token = inject(AuthRegularService).getToken();
constructor(private _zone: NgZone) {}
getServerSentEvent(url: string): Observable<any> {
return Observable.create((observer: any) => {
const eventSource = this.getEventSource(url);
eventSource.onmessage = (event) => {
this._zone.run(() => {
// console.log("SSE event data received: ", event.data)
if (!event.data) {
console.log('False data received', event.data);
// do not forward as this causes an error, "", false, undefined, null
} else if (JSON.parse(event.data).msg === 'PROCESS_ENDED') {
eventSource.close();
observer.next(event);
} else {
observer.next(event);
}
});
};
eventSource.onerror = (error: any) => {
console.log('Getting server sent event error:', error);
eventSource.close();
return;
// this._zone.run(() => {
// observer.error(error);
// });
};
});
}
private getEventSource(url: string): EventSource {
return new CustomEventSource(url, {
headers: {
Authorization: 'Bearer ' + this.token,
},
retry: 3000,
});
}
}
In several places this package uses console
methods to write directly to standard output. This can be problematic when used from a CLI program where I want to have full control over my program's output. Currently I'm seeing messages like Connection established
in my output which I have no straightforward way of preventing.
Would you consider accepting a pull request which removes all usages of console.*
? Or if not, perhaps a new option to allow some mechanism to disable them?
How would I extract an 401 from the event in onerror
?
I can do this:
eventSource.addEventListener('specific-event-type', msg => { ... });
And it'll fire, but
eventSource.onmessage = msg => { .... }
Will never fire.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.