добавить задержку в двойной петле - PullRequest
1 голос
/ 21 января 2020

В этом коде (источник: eloquent javascript) я хочу добавить задержку в 1 секунду для любого из этих двух циклов, но я никак не могу это сделать. Я хотел бы посмотреть, как это можно решить с помощью setTimeout для каждого из циклов и для обоих (спасибо, что каждая итерация будет выполняться 1 секунда одна за другой. Мне не удалось получить эту работу из похожих вопросов / ответов.

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";
}

console.log(board);

Ответы [ 2 ]

2 голосов
/ 21 января 2020

Вы можете использовать генераторы в сочетании с setinterval для вызова iterator#next каждую секунду. Так что в следующем примере просто наберите yield board всякий раз, когда вы хотите подождать 1 секунду.

function* looping() {
  let board = "";
  for (let y = 0; y < 8; y++) {
    for (let x = 0; x < 8; x++) {
      board += (x + y) % 2 ? "#" : " ";
      yield board;
    }
    board += "\n";
  }
  return board;
}

var iterator = looping();

(function iife() {
  setTimeout(function() {
    var result = iterator.next();
    document.querySelector("#result").textContent = result.value;
    if (!result.done) iife();
    else console.log("Done");
  }, 1000);
})();
#result {
  white-space: pre;
}

#result::before,
#result::after {
  content: '"';
}
<div id="result"></div>
1 голос
/ 21 января 2020

Мы можем разделить ваш дисплей и логи обработки 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, '&nbsp'); //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, '&nbsp'); //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>
...