workers threads thread example end ejemplos javascript jquery firefox server-sent-events worker

javascript - threads - ¿Cómo hacer que EventSource esté disponible dentro de SharedWorker en Firefox?



web workers html5 ejemplos (1)

Estoy tratando de implementar eventos enviados por el servidor (SSE) dentro de SharedWorker.

La implementación funciona sin problemas en Google Chrome. Sin embargo, no funciona en Firefox en absoluto.

Cuando intento que funcione en Firefox, aparece este error en la consola.

error { target: SharedWorker, isTrusted: true, message: "ReferenceError: EventSource is not defined", filename: "https://example.com/add-ons/icws/js/worker.js", lineno: 28, colno: 0, currentTarget: SharedWorker, eventPhase: 2, bubbles: false, cancelable: true, defaultPrevented: false }

¿Cómo puedo hacer que EventSource esté disponible dentro de SharedWorker ?

Así es como establezco la conexión the SharedWorker

$(window).load(function(){ //establish connection to the shared worker var worker = new SharedWorker("/add-ons/icws/js/worker.js" ); //listen for a message send from the worker worker.port.addEventListener("message", function(event) { console.log( Math.random() ); processServerData(event.data); } , false ); worker.onerror = function(event){ console.log(event); }; //start the connection to the shared worker worker.port.start(); });

Este es mi script de trabajador

var clients = new Array(); readNewMessages(); //runs only when a new connection starts onconnect = function(event) { var port = event.ports[0]; clients.push(port); port.start(); //implement a channel for a communication between the connecter and the SharedWorker port.addEventListener("message", function(event) { replyToClientMessage(event, port); } , false ); } //reply to any message sent to the SharedWorker replyToClientMessage = function (event, port) { port.postMessage(event.data); } //runs every time and post the message to all the connected client function readNewMessages(){ var serv = new EventSource(''/add-ons/icws/poll.php''); serv.addEventListener("getMessagingQueue", function(event) { var queue = JSON.parse(event.data); notifyAllPorts(queue); }, false); } //check all open clients and post a message to each function notifyAllPorts(msg){ var len = clients.length; var port; for(i = 0; i < len; i++) { port = clients[i]; port.postMessage(msg); } }

Mientras buscaba una solución, descubrí que EventSource no forma parte de SharedWorkerGlobalScope

Traté de cambiar mi código de trabajador a esto, pero aún así eso no funcionó

var serv = new self.EventSource(''/add-ons/icws/poll.php''); var clients = new Array(); readNewMessages(); //runs only when a new connection starts onconnect = function(event) { var port = event.ports[0]; clients.push(port); port.start(); //implement a channel for a communication between the connecter and the SharedWorker port.addEventListener("message", function(event) { replyToClientMessage(event, port); } , false ); } //reply to any message sent to the SharedWorker with the same message but add the phrase "SharedWorker Said: " to it replyToClientMessage = function (event, port) { port.postMessage(event.data); } //runs every time and post the message to all the connected client function readNewMessages(){ serv.addEventListener("getMessagingQueue", function(event) { var queue = JSON.parse(event.data); notifyAllPorts(queue); }, false); } //check all open clients and post a message to each function notifyAllPorts(msg){ var len = clients.length; var port; for(i = 0; i < len; i++) { port = clients[i]; port.postMessage(msg); } }

¿Cómo puede solucionar este problema?


Por qué FF le permitiría tener un WebSocket en un Worker pero no en un EventSource, no estoy seguro, pero le da todas las herramientas para hacer un buen polyfill (pegarlo en la parte superior de su script de SharedWorker):

//FF only; some missing functionality, but handles the essentials //most of what''s missing can be added if you have the motivation (function(global) { if (''EventSource'' in global) return; function EventSource(url) { if (!(this instanceof EventSource)) return new EventSource(url); this.url = url; var self = this; var listeners = {}; self.addEventListener = function(type, handler) { if (!listeners[type]) { listeners[type] = new Set(); } listeners[type].add(handler); }; self.removeEventListener = function(type, handler) { if (listeners[type]) { listeners[type].delete(handler); } }; self.dispatchEvent = function(event) { if (listeners[event.type]) { listeners[event.type].forEach(function(handler) { setTimeout(function() { switch (typeof(handler)) { case ''object'': handler.handleEvent(event); break; case ''function'': handler(event); break; } }); }); } if (typeof(self[''on'' + event.type.toLowerCase()]) == ''function'') { setTimeout(function() { self[''on'' + event.type.toLowerCase()](event); }); } }; var buffer = ''''; //if you want to handle other prefixes, you''ll need to tweak these var msgRE = /^(?:data: .*/n)*/n/; var dataRE = /^data: (.*)$/; function _parse() { while (msgRE.test(buffer)) { var msg = msgRE.exec(buffer)[0]; //msg now contains a single raw message var data = null; var lines = msg.split("/n").slice(0, -2); //remove last 2 newlines if (lines.length) { data = ''''; lines.forEach(function(line) { data += dataRE.exec(line)[1]; }); } var event = new MessageEvent(''message'', { ''data'' : data, ''origin'' : url }); self.dispatchEvent(event); buffer = buffer.substr(msg.length); } } var xhr = new XMLHttpRequest(); xhr.open(''GET'', url, true); xhr.responseType = ''moz-chunked-text''; //FF only xhr.setRequestHeader(''Accept'', ''text/event-stream''); xhr.onprogress = function() { if (xhr.response !== null) { buffer += xhr.response; } _parse(); }; xhr.onreadystatechange = function() { switch (xhr.readyState) { case XMLHttpRequest.HEADERS_RECEIVED: if (xhr.status == 200) { self.readyState = EventSource.OPEN; break; } //else console.error("EventSource: " + url + " = " + xhr.statusText); //fallthrough case XMLHttpRequest.DONE: self.readyState = EventSource.CLOSED; break; default: break; } }; xhr.send(); Object.defineProperty(this, ''close'', { ''value'' : function() { xhr.abort(); }}); return this; } Object.defineProperties(EventSource, { ''CONNECTING'' : { ''value'' : 0, ''enumerable'' : true }, ''OPEN'' : { ''value'' : 1, ''enumerable'' : true }, ''CLOSED'' : { ''value'' : 2, ''enumerable'' : true }, }); EventSource.prototype = Object.create(EventTarget.prototype); Object.defineProperties(EventSource.prototype, { ''constructor'' : { ''value'' : EventSource }, ''readyState'' : { ''value'' : 0, ''writable'' : true, ''enumerable'' : true }, ''withCredentials'' : { ''value'' : false, ''enumerable'' : true }, //not supported ''onopen'' : { ''writable'' : true }, ''onmessage'' : { ''writable'' : true }, ''onerror'' : { ''writable'' : true }, ''close'' : { ''value'' : function() { }, ''configurable'' : true, ''enumerable'' : true } }); global.EventSource = EventSource; })(this);

Puede encontrar más rellenos completos aquí y aquí . Necesitaba uno que funcione con una transmisión en caché en tiempo real (si no está conectado a la transmisión cuando ocurre el evento, se va); esto es lo que se me ocurrió La principal diferencia es el tipo de respuesta moz-chunked-text, que le da acceso a la secuencia de almacenamiento en memoria caché en el evento de progreso. Disfruta ;-)