In my code i want to loop again once a certain condition if(i === arr.length) matched. here is the demo code. any idea how can i solve it?
var arr = [1,2,3];
for (let i = 0; i < arr.length; i++)
{
setTimeout( function timer()
{
console.log("test");
if(i === arr.length){
// start the looping after this condition match
}
}, i*3000 );
}
Your code never reaches the condition since i < arr.length is your exit,
if you change it to i <= arr.length then the condition will be reached,
then to re-enter the loop i suggest that you encapsulate all your loop in a function
var arr = [1,2,3];
for (let i = 0; i < arr.length; i++)
{
setTimeout( function timer()
{
console.log("test");
if(i === arr.length){
// start the looping after this condition match
}
}, i*3000 );
}
To
var arr = [1,2,3];
function Looper(){
for (let i = 0; i <= arr.length; i++)
{
setTimeout( function timer()
{
console.log("test");
if(i === arr.length){
Looper();
}
}, i*3000 );
}
}
Looper();
Keep in mind that this is an infinite loop, you would better use setInterval, if thats your goal, but if you have something else in mind hope this helps.
The problem with your code as it is now is the loop is exited before even the first setTimeout call back runs. The addition of a console.log after the loop confirms this.
var arr = [1,2,3];
for (let i = 0; i < arr.length; i++)
{
setTimeout( function timer()
{
console.log("test");
if(i === arr.length){
// start the looping after this condition match
}
}, i*3000 );
}
console.log("Loop exited");
So there is no way to restart that loop. However you can re-organise your code to keep looping over your arr with a 3000ms delay. The easiest is probably with a Promise.
var arr = [1,2,3];
async function doWork(item){
return new Promise(resolve => {
setTimeout(() => {
console.log("finished",item); // do whatever you want to do here
resolve();
},3000);
});
}
async function test(){
var exit = false; // if you set this to true elsewhere the code will stop
var i = 0;
while(!exit){
var item = arr[i++ % arr.length];
await doWork(item);
}
}
test();
Here is simple attempt hope you'll find it helpful
var arr = [1, 2, 3];
var i = 0;
var i = 0;
function timer() {
console.log(arr[i])
i = (i + 1) % arr.length;
}
setInterval(timer, 1000);
Related
This question already has answers here:
Why is the method executed immediately when I use setTimeout?
(8 answers)
Calling functions with setTimeout()
(6 answers)
Combination of async function + await + setTimeout
(17 answers)
Closed 7 months ago.
I have a program which is supposed to demonstrate a bubble sort, however I want the program to wait one second after every swap to demonstrate what swap is being made. Attached is my code:
function bubbleSort(arr){
for(var i = 0; i < arr.length-1; i++){
for(var j = 0; j < arr.length-i-1; j++){
if(arr[j] > arr[j+1]){
swap(arr,j,j+1);
}
}
}
}
Here is my swap function:
async function swap (arr,a,b){
var temp = arr[a];
var temp2 = arr;
temp2[a] = arr[b];
temp2[b] = temp;
await setTimeout(updateText(),1000);
return temp2;
}
And here is updateText:
function updateText(arrayText){
document.getElementById('arrayText').innerHTML = printArray(arr);
}
Whenever I execute the bubbleSort() function, my array goes from unsorted to sorted instantly, and does not show the swaps needed to reach the solved array.
updateText() is not called anywhere else in my program except for in the swap function.
Any help would be greatly appreciated and I can provide clarifications if needed.
The issue is the setTimeout function does not return a promise, which await expects.
function resolveAfter1Second() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 1000);
});
}
async function swap (arr,a,b){
var temp = arr[a];
var temp2 = arr;
temp2[a] = arr[b];
temp2[b] = temp;
await resolveAfter1Second();
return temp2;
}
Here's an example that simply logs the array to the console. You can replace the console.log(arr) line with a web page update, as needed.
const waitFor = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
async function bubbleSort(arr) {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
await swap(arr, j, j + 1);
}
}
}
}
async function swap(arr, a, b) {
[arr[a], arr[b]] = [arr[b], arr[a]]
console.log(arr);
return waitFor(1000);
}
const array = [10, 9, 4, 5, 3, 1, 2];
bubbleSort(array);
The following function -
a = [1,2,3];
function f() {
for(let i=0; i < a.length; i++){
setTimeout(() => console.log(i),3000)
}
}
gives me output - 0,1,2 which is as expected.
However, the following function -
function f() {
for(var i=0; i < a.length; i++){
setTimeout((function(el){console.log(el)})(i),3000)
}
}
gives the following output -
0 and throws following error
Uncaught TypeError: Cannot read property '__wrapper_2__' of undefined
However, in the last function if I remove setTimeout, I am getting expected behavior i.e. -
function f() {
for(let i=0; i < a.length; i++){ (function(i){console.log(i)})(i);
}
}
I am getting the expected output - 0,1,2
So, Why setTimeout is giving me error with when defining new function, but not with arrow functions ?
You're attempting to call the function in the argument list. It doesn't work for the same reason this doesn't:
function f() {
for (let i = 0; i < a.length; i++) {
setTimeout(console.log(i), 3000);
}
}
f();
The first argument of setTimeout is an uncalled function, like:
setTimeout(() => console.log(i), 1000);
or
const method = () => console.log(i);
setTimeout(method, 1000)
Edit: Also,
function f() {
for (var i = 0; i < a.length; i++) {
setTimeout(() => {
(function (el) {
console.log(el);
})(i);
}, 3000);
}
}
let a = [1, 2, 3];
f();
Will return 3, 3, 3 because after 3000ms the given function will be called with the global variable i as a parameter, and at that point i === 3;
However, in the following example, the value of i at the time is saved in the function. I believe that has something to do with closures, maybe someone else can follow up with a better explanation of that.
function f() {
for (var i = 0; i < a.length; i++) {
setTimeout(() => {
console.log(i);
}, 3000);
}
}
let a = [1, 2, 3];
f();
I am working through some Javascript coding problems and I want to print the output of the array on my command line using node file.js but I keep getting undefined as the output. Not sure what I am doing wrong. I've tried adding a console.log statement in different areas of the code. Here is the code:
var sortArrayByParity = function(A) {
E = [];
O = [];
for (i = 0; i < A; i++){
if (A[i] % 2 === 0){
E.push(A[i]);
}
else {
O.push(A[i]);
}
}
return E.concat(O);
console.log(E);
};
You have a few issues with your code:
The console.log() after your return will not run, as any code after a return will not be executed as the function is no longer running.
Another issue is your for loop. Currently, you are not looping as your condition i < A isn't correct. Instead, you want to loop over the length of A using:
for(var i = 0; i < A.length; i++) {
// Do code
}
See example below:
var sortArrayByParity = function(A) {
E = [];
O = [];
for (var i = 0; i < A.length; i++) {
if (A[i] % 2 === 0) {
E.push(A[i]);
} else {
O.push(A[i]);
}
}
return E.concat(O);
};
var res = sortArrayByParity([1, 2, 3, 4]);
console.log(res); // [2, 4, 1, 3] (sorted by evens first, odds second)
well there is some validation you should do.
Make sure to pass an array
You missing to add the A.length in the for loop
var sortArrayByParity = function(A) {
let E = [];
let O = [];
let errMsg = ''
// Make sure you're passing and array
if ( ! A instanceof Array ) {
return errMsg = ' Argument is not an array '
}
for (let i = 0; i < A.length; i++){
if (A[i] % 2 === 0){
E.push(A[i]);
}
else {
O.push(A[i]);
}
}
console.log(E);
return E.concat(O);
};
this should work ;)
My code will log all 10 lines in the order that I want (descending triangle), but I need it to delay 1 second before logging each successive line. I tried putting a setTimeout before the for loop, but that just caused a 1 second delay before printing all 10 lines concurrently.
function minusTen(num) {
var arr = '';
for (var i = num; i > 0; i--) {
arr += '*';
}
var newArr = arr.split('');
for (var j = num; j > 0; j--) {
newArr.pop();
console.log(newArr.join(' '));
}
}
minusTen(10);
I can use jQuery but I'd like to avoid having to implement Bootstrap if possible.
Thank you!
you can use setTimeout for it but then you will have to keep setTimeout inside the for loop. you can also use setInterval here and clear the interval if num becomes 0. something like this:
function minusTen(num) {
var arr = '';
for (var i = num; i > 0; i--) {
arr += '*';
}
var newArr = arr.split('');
var interval = setInterval(function(){
newArr.pop();
console.log(newArr.join(' '));
num--;
if(!num)
clearInterval(interval);
}, 1000)
}
minusTen(10);
You can use a function. Check the .length of newArr, if greater than 0, call function again
function minusTen(num) {
var arr = '';
for (var i = num; i > 0; i--) {
arr += '*';
}
var newArr = arr.split('');
function fn() {
if (newArr.length)
setTimeout(function() {
console.log(newArr.join(" "));
newArr.pop();
fn()
}, 1000)
else
console.log("done, newArr.length:", newArr.length);
}
fn()
}
minusTen(10);
function minusTen(num) {
var arr = '';
for (var i = num; i > 0; i--) {
arr += '*';
}
var newArr = arr.split('');
function printLine(counter){
var k = counter;
window.setTimeout(function(){
console.log(newArr.join(' '));
newArr.pop();
}, k*1000);
console.log(k);
}
for (var j = num; j > 0; j--) {
printLine(j);
}
}
minusTen(10);
It's straightforward with async/await. delay holds the execution of the code for a specified amount of time.
async function minusTen(num) {
var arr = '';
for (var i = num; i > 0; i--) {
arr += '*';
}
var newArr = arr.split('');
for (var j = num; j > 0; j--) {
newArr.pop();
await delay(1000)
console.log(newArr.join(' '));
}
}
function delay(time) {
return new Promise((resolve) => setTimeout(resolve, time))
}
minusTen(10);
You can use setTimeout with an offset. Just add whatever parameters you need to the log function.
function log(offSet) {
setTimeout(() => {
const str = new Array(offSet + 1).join('*');
console.log(str);
}, 1000 * offSet);
}
for(let i = 1; i < 11; i ++) {
log(i);
}
https://jsfiddle.net/ycreaL9w/
If you wanted to reduce your code footprint a little you could do something like this:
const printStars = (n) => {
// Make sure we don't try to print zero stars
if (n > 0) {
// Fill an array with n stars
const arr = Array(n).fill('*').join(' ');
console.log(arr);
// After a second, reduce n by 1 and call
// the function again
setTimeout(() => printStars(--n), 1000);
}
}
printStars(10);
DEMO
It's worth pointing out here, however, that IE/Opera don't support Array.fill.
If you need to support them use an for/loop like in your example. Here I've separated out that code into its own function.
const getStars = (n) => {
let arr = [];
for (let i = 0; i < n; i++) {
arr.push('*');
}
return arr.join(' ');
}
const printStars = (n) => {
if (n > 0) {
console.log(getStars(n));
setTimeout(() => printStars(--n), 1000);
}
}
DEMO 2
I have an async function named populateFavoriteItem in for loop :
var result = [];
for (var i = 0; i <array.length ; i++) {
populateFavoriteItem(accountId,array[i],function(doc){
result.push(doc);
//mark 1
})
// if (i == array.length - 1) {
// console.log(result);
// callback(result);
// }
}
//mark 2
console.log(result);
callback(result);
It always run mark 2 first and then run to mark 1. Therefore, I get a null result array. Seems that result is not the populateFavoriteItem callback function.
Im trying to write if() condition in the for loop but get the same consequence, what should I do?
Use Node.js eventEmitter:
var result = [];
var obj;
var j = 0;
var myEventEmitter = new eventEmitter;
myEventEmitter.on('next',addResult);
function addResult(){
result.push(obj)
j++;
if (j == array.length) {
callback(result);
}
}
var populateFav = promiseify(populateFavoriteItem);
for (var i = 0; i <array.length ; i++) {
var ii = i;
populateFavoriteItem(accountId,array[ii],function(doc){
//result.push(doc);
obj = doc;
myEventEmitter.emit("next");
})
}