Javascript add delay in loop by condition - javascript

This is my code
var count = 1;
for (var key in result.data) {
if (count == 10) {
// I want to delay 1 second here
}
var value = result.data[key];
generate(key, value);
count++;
}
As you see , I iterate throught result.data , and added count to determine when to add delay.
I just want to add 1 second delay inside this loop when count == 10 as I shown .

You can use async/await to pause for a sec. Like this.
(async () => {
let count = 1;
const array = [1,2,3,4,5,6,7,8,1,2,3,4,5];
for (let key in array) {
if (count === 10) {
await new Promise((resolve) => {
console.log('Paused for 1 sec');
setTimeout(() => {
console.log('Continued');
resolve();
}, 1000);
});
}
console.log(key);
count++;
}
})();

Maybe it helps you:
function delay(functionToDelay, ms) {
return function() {
var savedThis = this;
var savedArguments = arguments;
setTimeout(function() {
functionToDelay.apply(savedThis, savedArguments);
}, ms);
};
}
First argument - function you want to delay.
Second - milliseconds

I'm assuming, you want to call the generate function after 1 second when the count is 10
You can use setTimeout like this:
var result = {
data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}
var count = 1;
for (let key in result.data) {
if (count == 10) {
setTimeout(() => generate(key, result.data[key]), 1000)
} else {
generate(key, result.data[key])
}
count++;
}
function generate(key, value) {
console.log(value);
}

What you need is setTimeout().
Your code will be something like this:
var count = 1;
for (var key in result.data) {
if (count == 10) {
// I want to delay 1 second here
setTimeout(function(){ alert("1 second delay!"); }, 1000);
}
var value = result.data[key];
generate(key, value);
count++;
}

Below you can find usable example for it.
PS: Edit
for (var key in result.data) {
if (count == 10) {
// I want to delay 1 second here
setTimeout(generate.bind(key, result.data[key]), 1000);
}
else
generate(key, result.data[key])
count++;
}

Related

Push array and loop until the array length reach 3

I am trying to push array a value until it reach the length of 3. I want also add delay to the loop. Any suggestion to fix the code. If the condition is met, break and go to next function. I am greatly appreciate it!
let array = [];
let eachEverySeconds = 1;
//function fetchCoinPrice(params) { //BinanceUS Fee: 0.00075 or 0.075%
function Firstloop() {
for (x = 0; x < 4; x++) {
setTimeout(function() {
function fetchCoinPrice() {
binance.prices(function(error, ticker) {
//array.push(ticker.BNBBTC);
//while(array.length<3){
//if (array.length<4){
array.push(ticker.BNBBTC);
console.log("1", array);
//}else {}//if (array.length === 3) { break; }
// array.shift();
});
}
}, 1000)
}
}
// setInterval(Firstloop, eachEverySeconds * 1000);
Firstloop()
You will need to save the interval into a variable that you can then use clearInterval() on.
Here's a mockup of what you're trying to accomplish.
var array = [];
var maxLength = 3;
var delay = 250; //I shortened your delay
var ticker = {}; //I'll use this to simulate your ticker object
var looper = setInterval(function() {
ticker.BNBBTC = Math.random(); //populating your ticker property w/random value
if (array.length < maxLength) {
array.push(ticker.BNBBTC);
} else {
console.log("Stopping the looper.");
clearInterval(looper);
console.log("Here are the contents of array");
console.log(array);
}
}, delay);
I'm not sure if I've understood your purpose as there are many commented codes there but if you want to run a function for three times and run it again after a second with new prices or ... may be this code helps you:
let array = [];
let eachEverySeconds = 1;
const loopArray = (array) => {
setTimeout(async () => {
if (array.length === 3) return;
let price = Math.random() * 10;
array.push(price);
await loopArray(array);
}, 1000 * eachEverySeconds);
console.log(array);
};
loopArray(array);

How to stop a recursive function?

So I have this code for my discord bot. It is suppose to check if the input entered by user is correct or not. Based on that run the command again by itself. I did it using recursive function. It works as long as user inputs correct string. But i want it to run only three times.
//Code
function recurssiveShit() {
var arr = [];
var i;
let hackString = "";
//create a unique 4 digits array
while (arr.length < 4) {
var r = Math.floor(Math.random() * 9) + 1;
if (arr.indexOf(r) === -1) arr.push(r);
}
console.log(arr);
//show the array to be sorted
message.channel.send("Write it in increasing order.\n" +
`\`${arr[0]},${arr[1]},${arr[2]},${arr[3]},\``);
//sort the array in increasing order
arr.sort((a, b) => a - b);
//store the sorted array as string
for (i = 0; i < 4; i++) {
hackString += arr[i];
}
//check is user's input is same as sorted array
message.channel.awaitMessages(filter, { max: 1, time: 6000 }).then(collected => {
let check = collected.first().content;
if (check === hackString) {
message.channel.send("Hack Successful");
recurssiveShit();
}
else {
return message.channel.send("Incorrect");
}
}).catch(err => {
console.log("Time ran out");
})
console.log(hackString);
}
recurssiveShit();
You could create a variable outside the function, increment it when needed, and check that it hasn't exceeded its limit before recursively firing another function.
var count = 0;
function recurssiveShit() {
var arr = [];
var i;
let hackString = '';
//create a unique 4 digits array
while (arr.length < 4) {
var r = Math.floor(Math.random() * 9) + 1;
if (arr.indexOf(r) === -1) arr.push(r);
}
console.log(arr);
//show the array to be sorted
message.channel.send(
'Write it in increasing order.\n' +
`\`${arr[0]},${arr[1]},${arr[2]},${arr[3]},\``
);
//sort the array in increasing order
arr.sort((a, b) => a - b);
//store the sorted array as string
for (i = 0; i < 4; i++) {
hackString += arr[i];
}
//check is user's input is same as sorted array
message.channel
.awaitMessages(filter, { max: 1, time: 6000 })
.then((collected) => {
let check = collected.first().content;
if (check === hackString) {
message.channel.send('Hack Successful');
if (++count !== 3) { // increment counter, than check if it equals three
recurssiveShit();
} else {
// code...
}
} else {
return message.channel.send('Incorrect');
}
})
.catch((err) => {
console.log('Time ran out');
});
console.log(hackString);
}
recurssiveShit();

JavaScript adding "return" method to an iterator doesn't properly close the iterator

I am learning the JavaScript ES6 iterator pattern and came across this problem:
const counter = [1, 2, 3, 4, 5];
const iter = counter[Symbol.iterator]();
iter.return = function() {
console.log("exiting early");
return { done: true };
};
for (let i of iter) {
console.log(i);
if (i >= 3) {
break;
}
}
console.log('---');
for (let i of iter) {
console.log(i);
}
// 1
// 2
// 3
// exiting early
// ---
// 4
// 5
So I added a return method definition to the iterator that I extracted from an array. Although the return method got called, it didn't actually close the iterator. By contrast, if I define the iterator return method in definition, it will work as expected:
class Counter {
[Symbol.iterator]() {
let count = 1;
return {
next() {
if (count <= 5) {
return {
done: false,
value: count++
}
} else {
return {
done: true,
value: undefined
}
}
},
return() {
console.log('exiting early');
return { done: true, value: undefined };
}
}
}
}
const myCounter = new Counter();
iter = myCounter[Symbol.iterator]();
for (let i of myCounter) {
console.log(i);
if (i >= 3) {
break;
}
}
console.log('---');
for (let i of myCounter) {
console.log(i);
}
// 1
// 2
// 3
// exiting early
// ---
// 1
// 2
// 3
// 4
// 5
My question is, why did I get this unexpected behavior? I assume that if the return method didn't get called, then the iterator will not close until it reaches the very end by calling next. But adding return property will properly "call" the return method since I got the console log, but doesn't actually terminate the iterator even if I returned { done: true } in the return method.
Neither of your two return methods actually close the iterator. To achieve that, they need to record the new state of the iterator, and by that cause the next method to also return {done: true} in all subsequent calls - that's what "closed" actually means.
We can see this behaviour in action with a generator:
const iter = function*(){ yield 1; yield 2; yield 3; }();
console.log(iter.next());
console.log(iter.return());
console.log(iter.next());
Your first snippet has the problem that you've overwritten iter.return, and your method gets called (as seen from the log) but it never actually closes iter. The underlying problem is that array iterators cannot be closed, they don't normally have a return method at all. You'd have to overwrite the iter.next method as well to simulate this.
Your second snippet has the problem that it's not actually trying to iterate the iter, but it's iterating the myCounter twice which creates a new iterator object for each loop. Instead we need to use a [Symbol.iterator] method that returns the same object multiple times, easiest done by having Counter implement the iterator interface itself. We can now reproduce the unexpected behaviour:
class Counter {
count = 1;
[Symbol.iterator]() {
return this;
}
next() {
if (this.count <= 5) {
return {done: false, value: this.count++ };
} else {
return {done: true, value: undefined};
}
}
return() {
console.log('exiting early');
return { done: true, value: undefined };
}
}
const iter = new Counter();
for (let i of iter) {
console.log(i);
if (i >= 3) {
break;
}
}
console.log('---');
for (let i of iter) {
console.log(i);
}
To fix the behaviour, we would close the iterator by having the return method set the count beyond 5:
class Counter {
count = 1;
[Symbol.iterator]() {
return this;
}
next() {
if (this.count <= 5) {
return {done: false, value: this.count++ };
} else {
return {done: true, value: undefined};
}
}
return() {
this.count = 6;
// ^^^^^^^^^^^^^^^
console.log('exiting early');
return { done: true, value: undefined };
}
}
const iter = new Counter();
for (let i of iter) {
console.log(i);
if (i >= 3) {
break;
}
}
console.log('---');
for (let i of iter) {
console.log(i); // not executed!
}
Your example can be simplified as
let count = 1;
const iter = {
[Symbol.iterator]() { return this; },
next() {
if (count <= 5) {
return {
done: false,
value: count++
}
} else {
return {
done: true,
value: undefined
}
}
},
return() {
console.log('exiting early');
return { done: true, value: undefined };
}
};
for (let i of iter) {
console.log(i);
if (i >= 3) {
break;
}
}
console.log('---');
for (let i of iter) {
console.log(i);
}
so iter is just a normal object. You are passing it to a for..of loop twice.
You are making incorrect assumptions about how the interface for iterators works. The core issue is that there is nothing in this code that stores and tracks the fact that iter has returned done: true once, and thus should continue to do so. If that is the behavior you want, you need to do that yourself, e.g.
let count = 1;
let done = false;
const iter = {
[Symbol.iterator]() { return this; },
next() {
if (!done && count <= 5) {
return {
value: count++
}
} else {
done = true;
return { done };
}
},
return() {
done = true;
console.log('exiting early');
return { done };
}
};
A for..of loop essentially calls .next() until the return result is done: true, and calls .return in some cases. It is up to the implementation of the iterator itself to ensure that it properly enters a "closed" state.
All of this can also be simplified by using a generator function, since generator objects have that internal "closed" state included automatically as a side-effect of the function having returned, e.g.
function* counter() {
let counter = 1;
while (counter <= 5) yield counter++;
}
const iter = counter();
for (let i of iter) {
console.log(i);
if (i >= 3) {
break;
}
}
console.log('---');
for (let i of iter) {
console.log(i);
}

How to construct a JavaScript for loop with a function

I'm constructing a loop for with a function.
The function loop takes a value, a test function, an update function, and a body function. Each iteration, it first runs the test function on the current loop value and stops if that returns false. Then it calls the body function, giving it the current value. Eventually, it calls the update function to create a new value and starts from the beginning.
loop(10, n => n > 0, n => n - 1, console.log);
function loop(a, b, c, d) {
let currentValue = a;
let i;
for (i = 0; i < currentValue; i++) {
if (b(currentValue)) {
d(currentValue);
update(c);
function update(c) {
var executeUpdate = c(currentValue);
currentValue = executeUpdate;
};
} else {
return;
}
};
}
// OUTPUT: 10, 9, 8, 7, 6
Why does this function stop at 6 instead of 1?
function update(c) {
var executeUpdate = c(currentValue);
console.log('value of exeucteUpdate: ',executeUpdate, 'when i:', i)
currentValue = executeUpdate;
};
Do a console.log at your update function, you will notice when i == 4, executeUpdate is 5 and you updated the value of forloop and hence the loop terminates at this particular loop
You can use few console.logs to see it.
Actually the for-cycle ends when currentValue and i equals 5, therefore the condition is not met and cycle terminates.
However your condition does not make any sense, you are comparing true to some number (as you can see in the logs)
loop(10, n => n > 0, n => n - 1, console.log);
function loop(a, b, c, d) {
let currentValue = a;
let i;
for (i = 0; i < currentValue; i++) {
console.log(i, currentValue);
console.log(b(currentValue), currentValue)
if (b(currentValue) < currentValue) {
d(currentValue);
update(c);
function update(c) {
var executeUpdate = c(currentValue);
currentValue = executeUpdate;
};
} else {
console.log('I am not here');
return;
}
}
console.log('finished', i, currentValue);
}

Javascript es6 array mapping

I need help creating a function that gonna return me 3 elements from an array each time with time interval of 3 seconds.
Let say I have an array
const Array = [{name:'A'},{name:'B'},{name:'C'},{name:'D'},{name:'E'},{name:'F'},{name:'G'},{name:'H'},{name:'I'}];
It should return array like
[{name:'A'},{name:'B'},{name:'C'}]
then after 3 seconds it should return array
[{name:'D'},{name:'E'},{name:'F'}]
And so on also when the arrays gets end repeat the loop again.
I tried using chunk where i used slice and filter but that just return me an array of chunks together.
Thanks so much
You can do this with a generator:
// Takes an array and the of the slice/subarray
function* subArray(array, size) {
let i = 0;
let remaining = true;
while (remaining) {
yield array.slice(i, i + size);
i += size;
if (i >= array.length) {
remaining = false;
}
}
}
// Takes an array, a subarray size, and an interval in seconds
const getSubArraysAtInterval = (array, size, seconds) => {
const iter = subArray(array, size);
const interval = setInterval(() => {
const next = iter.next();
if (next.done) {
clearInterval(interval);
console.log('No values remaining');
} else {
console.log(next.value);
}
}, seconds * 1000)
}
getSubArraysAtInterval([1, 2, 3, 4, 5, 6], 3, 3);
Working fiddle: https://jsfiddle.net/adrice727/msx3sf03/1/
const array = [{name:'A'},{name:'B'},{name:'C'},{name:'D'},{name:'E'},
{name:'F'},{name:'G'},{name:'H'},{name:'I'}];
let i = 0
setInterval(() => {
console.log(array.slice(i,i+3))
i*3 > array.length ? i=0 : i += 3
}, 3000)
The jsbin: https://jsbin.com/yoqelu/edit?html,js,console,output

Categories

Resources