Reputation: 13
In this code (source: eloquent javascript) i want to add a delay of 1 second for any of these 2 loops but i do not manage in any way. I would like to see how that can be solved with setTimeout for each of loops and for both (each iteration to be executed 1 second one after the other, thank you. I failed to get this working from similar questions/answers.
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);
Upvotes: 1
Views: 150
Reputation: 888
var count = 0;
/*
Parameters:
array: []
fnc: function (the business logic in form of function-,what you want to execute)
delay: milisecond
*/
function delayLoop(array,fnc,delay){
if(!array || array.legth == 0)return false;
setTimeout(function(data){
var data = array[count++];
fnc && fnc(data);
//recursion...
if(count < array.length)
delayLoop(array,fnc,delay);
else count = 0;
},delay);
}
Upvotes: 0
Reputation: 29022
We can split up your display and processing logic via a very simple implementation of the publish-subscribe pattern. We need basically threse things
board
every time.setInterval
that would do periodic polling of the message queue and if there are messages, would forward them.A commercial publish-subscribe system is likely to have a lot of bells and whistles - multiple queues/channels, message filtering, topics, storage of consumed events, etc. We don't really need all of that for this case but it's useful to mention that the following is an example of how pub-sub systems work, rather than a full implementation. Still, we don't necessarily need all of that for this problem. Here is a rudimentary implementation:
//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)
}
As mentioned, this is an overview of how this can work. Note that the implementation is closer to observer but doesn't act at the same moment as the change. At times design patterns may blur the lines between each other, especially depending on how they are used.
At any rate, the advantage of this pattern is that you can decouple your display (data consumption) logic to the calculations (data production). Your algorithm doesn't need to change if you want to add different consumers for the data it produces.
We can expand this to include multiple subscribers easily:
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>
Or here is a minor variation where you can add subscribers that work at different schedules:
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>
Upvotes: 1
Reputation: 7285
You could use generators in combination with setinterval to call iterator#next
every second. So in the following example, just do yield board
whenever you want to wait 1 second.
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>
Upvotes: 2