react-event-test
Version:
Event-driven alternative to React Context
118 lines • 3.46 kB
JavaScript
let WebSocketImpl;
if (typeof window !== "undefined" && window.WebSocket) {
WebSocketImpl = window.WebSocket;
}
else {
WebSocketImpl = undefined;
}
import React from 'react';
const subscriptions = {};
const messages = new Map();
let socket = null;
let sendQueue = [];
let isConnecting = false;
async function getWebSocketImpl() {
if (WebSocketImpl)
return WebSocketImpl;
const ws = await import('ws');
WebSocketImpl = ws.default;
return WebSocketImpl;
}
function connect(url) {
if (!socket) {
if (WebSocketImpl) {
socket = new WebSocketImpl(url);
}
else {
getWebSocketImpl().then((Impl) => {
socket = new Impl(url);
});
return null;
}
isConnecting = true;
socket.onopen = () => {
isConnecting = false;
// Kuyruktaki mesajları gönder
while (sendQueue.length > 0) {
socket.send(sendQueue.shift());
}
};
socket.onmessage = (msg) => {
try {
const { event, data } = JSON.parse(msg.data);
messages.set(event, data);
Object.keys(subscriptions[event] || {}).forEach((key) => {
const registry = subscriptions[event][key];
setTimeout(() => {
registry.callback(data, registry);
}, 0);
});
}
catch { }
};
socket.onclose = () => {
socket = null;
isConnecting = false;
};
}
return socket;
}
const subscribe = (...args) => {
if (args.length < 3) {
throw new Error('subscribe requires at least 3 arguments: url, event, callback');
}
const callback = args.pop();
const event = args.pop();
const url = args[0];
if (!subscriptions[event])
subscriptions[event] = {};
const id = Math.random().toString(36).slice(2);
const registry = {
id,
event,
callback,
unsubscribe: () => {
delete subscriptions[event][id];
if (Object.keys(subscriptions[event]).length === 0)
delete subscriptions[event];
},
};
subscriptions[event][id] = registry;
let last = messages.get(event);
if (last)
callback(last, registry);
return registry;
};
const publish = (...args) => {
if (args.length < 3)
throw new Error('publish requires at least 3 arguments: url, event, payload');
const payload = args.pop();
const event = args.pop();
const url = args[0];
const ws = connect(url);
const msg = JSON.stringify({ event, data: payload });
if (ws.readyState === 1) {
ws.send(msg);
}
else {
sendQueue.push(msg);
}
};
function last(event, init) {
if (messages.has(event))
return messages.get(event);
return init;
}
const useEvent = (...args) => {
const init = args.pop();
const event = args.pop();
const url = args[0];
const [payload, setPayload] = React.useState(last(event, init));
React.useEffect(() => {
const registry = subscribe(url, event, (data) => setPayload(data));
return () => registry.unsubscribe();
}, [url, event]);
return [payload, (data) => publish(url, event, data)];
};
export { subscribe, publish, useEvent };
//# sourceMappingURL=index.js.map