Я создал ShareWorker, используя этот скрипт.
// sharedWorker.js
importScripts('https://cdn.socket.io/4.3.1/socket.io.min.js');
let socket
let browserInstances = []
let counter = 0
onconnect = function(e) {
const port = e.ports[0]
browserInstances.push(port)
if (!socket) {
socket = io('socket-url');
socket.on('message', (message) => {
const msg = JSON.parse(message)
browserInstances.map(instance => {
instance.postMessage({type: msg.type, data: msg.data});
});
});
}
}
я получаю два типа сообщений из сокета один — {тип: 'уведомление', данные: '12345'} а другой – {type: 'event', data: '12345'}
теперь есть два прослушивателя: один из них — мой основной компонент App.tsx, а другой — в моем дочернем компоненте.
это мой прослушиватель App.tsx
worker.port.onmessage = (event: any) => {
console.info(event.data)
if (event.data.type === 'notification') {
console.info('Notification received:', event.data.data);
// Handle notification logic here
}
// Do not consume the message, let it propagate to other components
return true;
}
и это мой прослушиватель childComponent.tsx
worker.port.onmessage = (event: any) => {
console.info(event)
if (event.data.type === 'event') {
console.info('Event received:', event.data.data);
// Handle event logic here
}
}
И вот мой код WorkerContext.tsx, где я запускаю работника
// WorkerContext.ts
import React, { createContext, useEffect, useState, ReactNode } from 'react';
export const WorkerContext = createContext<any | undefined>(undefined);
interface WorkerProviderProps {
children: ReactNode;
}
export const WorkerProvider: React.FC<WorkerProviderProps> = ({ children }) => {
const [worker, setWorker] = useState<SharedWorker | null>(null);
useEffect(() => {
const sharedWorker = new SharedWorker('/sharedWorker.js');
setWorker(sharedWorker);
return () => {
sharedWorker.port.close();
};
}, []);
return (
<WorkerContext.Provider value = {{ worker }}>
{children}
</WorkerContext.Provider>
);
};
Проблема в том, что он получает сообщения только в компоненте App.tsx, сообщения не передаются в childComponent.tsx, но когда я удаляю прослушиватель App.tsx, они передаются в childComponent. Как я могу передать сообщение в приложение и дочерний компонент в зависимости от типа данных?
он указывает на того же работника, что и я создал работника, используя ContextApi
Однако вы на самом деле не показываете, как создали рабочего. Не могли бы вы отредактировать это в вашем вопросе?
Я отредактировал свой вопрос и поместил туда код
worker.port.onmessage = ___
присваивается свойству onmessage
, перезаписывая любое значение, которое оно имело раньше (таким образом удаляя любой предыдущий прослушиватель событий, настроенный таким же образом). Вместо этого используйте worker.port.addEventListener("message", ___);
, чтобы у вас было несколько слушателей события. См. документацию EventTarget
для addEventListener (MessagePort
— подкласс EventTarget
). Вам также необходимо вызвать start() на порту (установщик onmessage
сделает это за вас).
когда я добавляю это worker.port.addEventListener("message", ___);
, оно не принимает никаких сообщений
@FaizanAhmad - Похоже, вы приняли ответ. Означает ли это, что ваш комментарий выше устарел?
Указывает ли
worker
на тот же экземплярSharedWorker
, что подразумевается в ответе ниже, или вы создаете новый экземпляр для каждого компонента?