!PubSub
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
const pubsubz = (() => {
const topics = {};
let subUid = -1; // index
return {
publish(topic, args) {
if (!topics[topic]) return false;
// Асинхронный вызов через очередь микрозадач
queueMicrotask(() => {
const subscribers = topics[topic];
if (subscribers) {
// Итерируемся с конца или используем forEach, чтобы избежать проблем с индексами
subscribers.forEach((sub) => sub.func(topic, args));
}
});
return true;
},
subscribe(topic, func) {
if (!topics[topic]) {
topics[topic] = [];
}
const token = (++subUid).toString();
topics[topic].push({token, func});
return token;
},
unsubscribe(token) {
for (const topic in topics) {
if (topics[topic]) {
const initialLength = topics[topic].length;
// Фильтруем массив, удаляя элемент с нужным токеном
topics[topic] = topics[topic].filter((sub) => sub.token !== token);
// Если элемент был удален, возвращаем токен
if (topics[topic].length !== initialLength) {
return token;
}
}
}
return false;
},
};
})();
// Тест (работает точно так же)
const testSubscriber = (topic, data) => console.log(`${topic}:`, data);
const testSubscription = pubsubz.subscribe("example1", testSubscriber); // token
pubsubz.publish("example1", "hello world!");
setTimeout(() => {
pubsubz.unsubscribe(testSubscription);
pubsubz.publish("example1", "hello again!"); // Не вызовется, так как отписка произойдет вовремя
}, 0);
JavaScript
INFO