Мы можем разделить ваш дисплей и логи обработки c с помощью очень простой реализации шаблона publi sh -subscribe . Нам нужны в основном три вещи
- Очередь сообщений или канал сообщений. В этом случае мы могли бы использовать массив - без причины, так как его проще всего реализовать.
- Издатель будет добавлять сообщения в очередь. В этом случае используемый вами алгоритм будет добавлять
board
каждый раз. - Подписчик, который будет что-то делать с каждой записью в массиве. В этом случае просто распечатайте его на консоли.
- Брокер сообщений - обычно это та часть, которая отправляет сообщения подписчикам. Здесь мы можем использовать простой
setInterval
, который будет выполнять периодический c опрос очереди сообщений и, если есть сообщения, переадресует их.
Коммерческая публикация sh -система подписки, скорее всего, имеет много наворотов - несколько очередей / каналов, фильтрация сообщений, темы, хранение потребляемых событий и т. Д. c. Нам не нужно все это для этого случая, но полезно упомянуть, что ниже приведен пример того, как работают системы pub-sub, а не полная реализация. Тем не менее, нам не обязательно все это нужно для решения этой проблемы. Вот элементарная реализация:
//the message queue
let queue = [];
//our message broker
setInterval(
() => {
if (queue.length !== 0) {
const frame = queue.shift();
//our subscriber
print(frame);
}
},
1000
);
//our publisher
function calculate() {
let board = "";
for (let y = 0; y < 8; y++) {
for (let x = 0; x < 8; x++) {
if ((x + y) % 2 == 0)
{board += " ";}
else {board += "#";}
}
board += "\n";
queue.push(board); //the publish action
}
}
calculate();
//just print to the console
function print(frame) {
console.log(frame)
}
Как уже упоминалось, это обзор того, как это может работать. Обратите внимание, что реализация ближе к наблюдателю , но не действует в тот же момент, что и изменение. Время от времени шаблоны проектирования могут стирать грани между собой, особенно в зависимости от того, как они используются.
В любом случае преимущество этого шаблона заключается в том, что вы можете отделить отображаемую логику (потребление данных) c от расчетов (производство данных). Ваш алгоритм не нуждается в изменении, если вы хотите добавить разных потребителей к производимым им данным.
Мы можем расширить это, чтобы легко включить несколько подписчиков:
let queue = [];
let subscribers = [];
//add to a pool of subscribers that will all run on the same schedule and consume messages
function subscribe(callback) {
subscribers.push(callback);
}
setInterval(
() => {
if (queue.length !== 0) {
const frame = queue.shift();
subscribers.forEach(sub => sub(frame));
}
},
1000
);
function calculate() {
let board = "";
for (let y = 0; y < 8; y++) {
for (let x = 0; x < 8; x++) {
if ((x + y) % 2 == 0)
{board += " ";}
else {board += "#";}
}
board += "\n";
queue.push(board);
}
}
subscribe(print);
subscribe(displayHTML);
calculate();
//just print to the console
function print(frame) {
console.log(frame);
}
//show as HTML on the page
function displayHTML(frame) {
const displayElement = document.getElementById("display_area");
//convert newlines for HTML display
const displayFrame = frame
.replace(/\n/g, '<br/>') //new lines to <br/> tags
.replace(/ /g, ' '); //spaces to non-breakable spaces
displayElement.innerHTML = displayFrame;
}
.as-console-wrapper {
/* resize the console otherwise it covers up the HTML display */
left: 300px !important;
}
<div id="display_area"></div>
Или вот небольшой вариант, когда вы можете добавлять подписчиков, которые работают с разными расписаниями:
let queue = [];
//add different subscribers that might work at different times through the messages
function subscribe(subscriberCallback, pollTimeMs) {
let lastFrameIndex = 0;
setInterval(
() => {
if (queue.length !== lastFrameIndex) {
//next message in the queue for this subscriber
const frame = queue[lastFrameIndex++];
subscriberCallback(frame);
}
},
pollTimeMs
);
}
function calculate() {
let board = "";
for (let y = 0; y < 8; y++) {
for (let x = 0; x < 8; x++) {
if ((x + y) % 2 == 0)
{board += " ";}
else {board += "#";}
}
board += "\n";
queue.push(board);
}
}
subscribe(print, 1000);
subscribe(displayHTML, 1500);
calculate();
//just print to the console
function print(frame) {
console.log(frame);
}
//show as HTML on the page
function displayHTML(frame) {
const displayElement = document.getElementById("display_area");
//convert newlines for HTML display
const displayFrame = frame
.replace(/\n/g, '<br/>') //new lines to <br/> tags
.replace(/ /g, ' '); //spaces to non-breakable spaces
displayElement.innerHTML = displayFrame;
}
.as-console-wrapper {
/* resize the console otherwise it covers up the HTML display */
left: 300px !important;
}
<div id="display_area"></div>