for (var i = 0; i <= 5000; i++) {
if(i % 5 == 0){
setTimeout(function() {
console.log(i);
}, 5000);
}
else{
console.log(i);
}
}
I want that once it reaches to number 5 then wait 5 seconds before displaying number 6 in the console. How can I achieve this?
I hope You meant this:
it console.log's non divideable to 5 numbers and then waits 5 second and goes again.
const wait = ms => {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
const URL = [...Array(5000).keys()].map(n => n * 2);
const serial = [...Array(5000).keys()].map(n => n * 10);
(async (URL, serial) => {
for (let i = 1; i <= 5000; i++) {
if (i % 5 === 0) {
await wait(5000);
const url = 'http://localhost:3000/?URL='+URL[i]+'&serial='+serial[i];
console.log('Opening url:', url);
window.open(url, '_blank');
continue;
}
await wait(500);
console.log(i);
}
})(URL, serial);
javascript is single thread, try not using blocking as it will freeze your entire program.
SetTimeout and recursion can do the job for you
function print(i,total) {
if (i >= total) {
return;
}
else if (i % 5 === 0) {
setTimeout(function(){
console.log(i);
return print(i+1,total);
},5000)
} else {
console.log(i);
return print(i+1, total);
}
}
print(1,100)
function st(i1) {
setTimeout(function () {
console.log(i1)
},5000)
}
function aa(st) {
return new Promise((resolve => {
for(var i=1;i<=10;i++){
if(i==5){
console.log(i)
i=i+1;
resolve(st(i))
break;
}
console.log(i)
}
}))
}
async function bb() {
var ss=await aa(st)
}
bb()
Related
I'm trying to show the process of how the backtracking algorithm solves a sudoku board, but I'm not sure how I can make sure that it only gets called every 500ms.
function solveBoard(board) {
// I tried doing setTimeout from here to the bottom, but it breaks the solver and just puts 9s everywhere.
let empty = findEmpty(board);
if (!empty) return true;
let row = empty[0];
let col = empty[1];
for (let i = 1; i < 10; i++) {
board[row][col] = i;
console.log(board[row][col]);
document.getElementById(`${row}-${col}`).value = i;
if (checkValid(board, row, col)) {
if (solveBoard(board)) {
return true;
}
}
board[row][col] = 0;
}
return false;
}
The first time I call solve board is just an event listener.
solveBtn.addEventListener("click", () => {
solveBoard(boardArray);
});
Call sleep in solveBoard
async function solveBoard(board) {
await sleep()
// …
}
function sleep(ms = 500) {
return new Promise(resolve => setTimeout(resolve, ms))
}
// Demo
(async () => {
console.log('a')
await sleep()
console.log('b')
await sleep()
console.log('c')
})();
I am making a screensaver that displays the elements inside an array with a delay between each iteration, to display the elements slowly one by one. My "onmousemove" event successfully removes the screensaver from the page, but the for loop in my startScreensaver() function keeps running when it should in fact break. What am I doing wrong?
see JSfiddle https://jsfiddle.net/m60k75jf/
const idletime = 2;
const screenSaver = document.getElementById("screensaver");
const stars = Array.from(document.querySelectorAll(".star"));
let mousetimeout;
let screensaverActive = false;
window.addEventListener("mousemove", (e) => {
clearTimeout(mousetimeout);
if (screensaverActive) {
stopScreensaver();
} else {
mousetimeout = setTimeout(function () {
startScreensaver();
}, 1000 * idletime);
}
});
function stopScreensaver() {
screensaverActive = false;
stars.forEach((star) => {
star.classList.remove("is--visible");
});
screenSaver.classList.remove("is--active");
}
function startScreensaver() {
screensaverActive = true;
screenSaver.classList.add("is--active");
for (let index = 0; index < stars.length; index++) {
if (screensaverActive) {
setTimeout(function () {
stars[index].classList.add("is--visible");
}, 2000 * index);
} else {
break;
}
}
}
You can't break the loop like that. Your loop creates all these setTimeout immediately. Your condition will just never trigger. What you'll need to do is clear out all those setTimeout. You can push them into an array.
let animationTimeouts;
function startScreensaver() {
animationTimeouts = [];
screensaverActive = true;
screenSaver.classList.add("is--active");
for (let index = 0; index < stars.length; index++) {
if (screensaverActive) {
animationTimeouts.push(setTimeout(function () {
stars[index].classList.add("is--visible");
}, 2000 * index));
} else {
break;
}
}
}
Then clear them out on stopScreensaver
function stopScreensaver() {
screensaverActive = false;
if(animationTimeouts) animationTimeouts.forEach(clearTimeout);
stars.forEach((star) => {
star.classList.remove("is--visible");
});
screenSaver.classList.remove("is--active");
}
You might also want to reconsider moving your CSS transition to .star.is--visible
I´m trying to execute an http get request to an api every 5 seconds from my reactjs app, although using the setTimeout function, after the first 5 seconds all the requests are done.
getPerson = (url) => {
axios.get(url)
.then(response => {
let person = {};
person.id = response.data.id;
person.name = response.data.name;
person.type = response.data.type;
this.state.persons.push(person);
this.setState({ persons: this.state.persons });
});
}
componentDidMount() {
for(var i = 1; i < 11; i++){
this.getPerson(this.apiUrl + i);
setTimeout(function () {
console.log("waiting for the next call.");
}, 5000);
}
}
componentDidMount() {
let i = 0;
let interval = setInterval(() => {
if (i<11) {
this.getPerson(this.apiUrl + i);
i++;
console.log("waiting for the next call.");
}
else {
clearInterval(interval)
}
}, 5000);
}
You should use setInterval() for that purpose, not setTimeout()
EDIT: In case you somehow don't have access to this in setInterval(), even though you should because it's an arrow function, you can use a workaround
let that = this and then call your method with that.getPerson(that.apiUrl + i);
Still having the problem to access "this" object from inside anonymous block function.
getPerson = (url) => {
axios.get(url)
.then(response => {
let person = {};
person.id = response.data.id;
person.name = response.data.name;
this.state.loadedPersons.push(person);
this.setState({ loadedPersons: this.state.loadedPersons });
});}
componentDidMount() {
for (var j = 1; j < 152; j++) {
this.getPerson(this.apiUrl + j);
}
let i = 1;
let that = this.state;
console.log("That out of in interval:" + that);
let interval = setInterval(function (that) {
console.log("That in interval:" + that);
if ((i<152))
that.persons.push(that.loadedPersons[i]);
i++;
}
else {
clearInterval(interval)
}
}, 5000);
}
Console output:
That out of interval: [Object object]
That in interval: undefined
I'm trying to understand how Promises are working and I can't get my piece of code to work.
class Lights {
constructor(delay) {
this.blue = 0;
this.green = 0;
this.red = 0;
this.delay = delay;
}
fadeIn(color, i) {
var self = this;
return new Promise(function(resolve, reject) {
setTimeout(function () {
self[color] = i;
console.log(self[color]);
i+=5;
if (i <= 255) {
self.fadeIn(color, i);
}
resolve(self);
}, self.delay);
});
}
fadeOut(color, i) {
var self = this;
return new Promise(function(resolve, reject) {
setTimeout(function () {
self[color] = i;
console.log(self[color]);
i-=5;
if (i >= 0) {
self.fadeIn(color, i);
}
resolve(self);
}, self.delay);
});
}
}
var lights = new Lights(50);
lights.fadeIn("blue", 0).then(
lights.fadeOut("blue", 255)
);
Here is a jsFiddle of the code.
The idea behind the code is to set the blue color from 0 to 255 and Then from 255 to 0. How can I do this ?
You are making recursive calls so on the last call what you resolve is not the resolve in your first promise that you call then on so you could store that first resolve in one property in your class and then call it.
class Lights {
constructor(delay) {
this.blue = 0;
this.green = 0;
this.red = 0;
this.delay = delay;
this.fadeInResolve = null;
this.fadeOutResolve = null;
}
fadeIn(color, i) {
return new Promise((resolve, reject) => {
if (!this.fadeInResolve) {
this.fadeInResolve = resolve
}
setTimeout(() => {
this[color] = i;
console.log(this[color]);
i += 5;
if (i <= 255) this.fadeIn(color, i);
else this.fadeInResolve(this)
}, this.delay);
});
}
fadeOut(color, i) {
return new Promise((resolve, reject) => {
if (!this.fadeOutResolve) {
this.fadeOutResolve = resolve
}
setTimeout(() => {
this[color] = i;
console.log(this[color]);
i -= 5;
if (i >= 0) this.fadeOut(color, i);
else this.fadeOutResolve(this)
}, this.delay);
});
}
}
var lights = new Lights(50);
lights.fadeIn("blue", 0).then(() => {
console.log('Fade in done')
lights.fadeOut("blue", 255).then(() => {
console.log('Fade out done')
})
});
Promise.prototype.then() should take a callback function and the recursion is not waiting. Consider this code which can be used to do the same thing:
//promisify :)
function timer(delay) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve();
}, delay);
});
}
class _Modulator {
constructor(_resolution = 255, _delay = 5) {
/* assert resolution and delay > 0; */
this._resolution = _resolution;
this._delay = _delay;
this._counter = 0;
this._running = false;
}
start() {
console.log("timer start");
this._running = true;
this._start();
}
_start() {
return timer(this._delay).then(() => {
if (this._running === true) {
this._counter += 1;
console.log("tick");
this._onTick();
/* care should be taken to ensure this will always catch, e.g.,
* correcting init
*/
if (this._counter === this._resolution) {
this._counter = 0;
this._onCycle();
}
this._start();
}
});
}
stop() {
this._running = false;
console.log("timer stopped");
}
_onTick() {
console.log("tick handle: %s", this._counter);
}
_onCycle() {
console.log("new cycle");
}
}
class UpDownModulator extends _Modulator {
constructor(_resolution = 255, _delay = 5) {
super(_resolution, _delay);
this._dir = 1;
}
_onTick() {
console.log("tick handle: %s", this.getCounter());
}
_onCycle() {
this._toggleDirection();
console.log("new cycle: going %s", this.getDirection());
}
_toggleDirection() {
this._dir ^= 1;
}
getCounter() {
return this._dir
? this._counter
: this._resolution - this._counter;
}
getDirection() {
return this._dir ? "up" : "down";
}
}
let c = new UpDownModulator();
c.start();
You can create a ColorFader class that depends on a Modulator and observe it. This creates clean abstractions that adhere to SRP.
I hope this helps!
I have an async function that has a loop that I need to be able to pause or unpause it. This is what I have so far.
I use a flag to pause the flow:
let flag = true;
function flag_func() {
flag = !flag;
}
$(document).ready(function () {
function sleep(ms) {
while (!flag) {
//...waiting.. but infinite loop
}
return new Promise(resolve => setTimeout(resolve, ms));
}
async function show_simulation(data) {
document.getElementById("solve-button").outerHTML = "<button type=\"button\" id='pause-button' onclick='flag_func()' class=\"btn btn-primary btn-lg\">Pause</button>";
//simulation
if (data.length === 0) {
console.log('stuff')
} else {
let i;
for (i = 0; i < data.length; i++) {
await sleep(40);
// do stuff
}
}
}
});
The problem is that is being paused, but due the while block the flow, I can't unpause the for loop.
Any idea about how I can solve this?
It might be a nice use case for async iterables. It involves a bit of boilerplate to create your async list, but then the code is much nicer. Basically you would have:
import AsyncList from './async-list.js'
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
async function f(data) {
const list = new AsyncList(data);
document.getElementById("btn-toggle").addEventListener("click", function () {
if (list.paused) {
this.textContent = "Pause";
list.resume();
} else {
this.textContent = "Resume";
list.pause()
}
})
for await (let item of list) {
console.log(item)
await sleep(1000);
}
console.log("end of loop")
}
f([10, "hello", 1029, 90, 80, 209, 44])
A possible implementation of AsyncList could be:
export default class AsyncList {
constructor(array) {
// shallow copy
this._array = array.slice();
this._index = 0;
this._length = this._array.length;
this.paused = false;
this._resume = () => {}; // noop, in case `resume` is called before `pause`
}
[Symbol.asyncIterator]() {
return this;
}
pause() {
this.paused = true;
}
resume() {
this.paused = false;
this._resume();
}
next() {
if (this._index < this._length) {
const value = this._array[this._index++];
if (this.paused) {
return new Promise(r => this._resume = r.bind(null, { value }))
}
return Promise.resolve({ value })
} else {
return Promise.resolve({ done: true });
}
}
}
Just to give to you the idea, you could also encapsulate the private properties, and check more scenarios (here I assume data is an array, for example, not just an iterable).
I'd replace:
let i;
for (i = 0; i < data.length; i++) {
await sleep(40);
// do stuff
}
...with...
let i = 0;
const doStuff = () => {
// do stuff
if (++i < data.length) {
setTimeout(doStuff, 40);
}
};
setTimeout(doStuff, 40);