I have two for loop, inside them I have setTimeout function like following code:
for(let i=0;i<3;i++){
setTimeout(()=>{console.log(i)}, 1000)
}
for(let i=0;i<3;i++){
setTimeout(()=>{console.log(i)}, 1000)
}
i want the second loop does not executed until after the first loop finished,
I want this result:
0
1
2
0
1
2
- and between 2 numbers wait 1 second.
how i can do that?
I can't comment yet or I would ask clarifying questions so I'll give you what I think you're asking for. If you want a 1 second delay between each number being logged to the console then this will work:
const func = async () => {
for (let i = 0; i < 3; i++) {
await new Promise((resolve) =>
setTimeout(() => {
console.log(i);
resolve();
}, 1000)
);
}
for (let i = 0; i < 3; i++) {
await new Promise((resolve) =>
setTimeout(() => {
console.log(i);
resolve();
}, 1000)
);
}
};
func();
A quick rundown of what's happening here. I created an outer function named func which I made asynchronous so that I can use the await keyword within it. I then put the setTimeout call inside a new instance of Promise. The promise combined with the await means that javascript will essentially stop at that line until the Promise calls resolve. Once resolve is called that instance of Promise is finished and the await statement stops "blocking" javascript and the callbackque continues.
TLDR:
To use await you must be in an asynchronous function.
If await is used in front of a Promise everything will stop until the promise resolves.
Placing the resolve of the promise inside the callback given to setTimeout ensures that we will wait until each timeout finishes BEFORE the next timeout begins.
This will work
nxt (0, 0);//seed the stack
function nxt(num, itertn){
if(num == 3){//want till 2
if(itertn == 0){// first or 2nd iteration
num =0;
itertn++;
}else{
return;//after 2nd stop
}
}
console.log(num);//the work
num++;
setTimeout(nxt, 1000, num, itertn);//next after a second
}
But there are other ways to do this
I think that you're trying to do sort of a counter
Try something like this:
for(let i=1;i<=3;i++){
setTimeout(()=>{ console.log(i)}, i*1000 )
}
Let me know if this solve your problem
Try nested loop
for(let i=0;i<2;i++){
for(let j=0;j<3;j++){
setTimeout(()=>{console.log(j)}, 1000)
}
}
One solution is create promises, and with map and promise.all, you can group each loop of promises and execute them sequentially.
(async () => {
const second = (i) => new Promise(resolve => setTimeout(() => {
console.log(i)
resolve(i)
}, 1000))
const loop = () => Array(3).fill(0).map(async(item, index) => {
return await second(index)
})
var startTime = performance.now()
await Promise.all(loop())
var endTime = performance.now()
console.log(endTime - startTime)
await Promise.all(loop())
endTime = performance.now()
console.log(endTime - startTime)
})()
Related
Having a list of number [n1,n2...] I want to print the number then sleep for t1, t2 print(n2) sleep for t2 etc.
I manage to "remember" the scope but the problem is that it waits always 1 second only.
also when i hardcode a larger value eg 2000 it just prints all the numbers.
With promises:
function sleep(ms) {
return(
new Promise(function(resolve, reject) {
setTimeout(function() { resolve(); }, ms);
});
);
}
for (let i = 1; i <= 100; i++) {
sleep(i*1000).then(function() {
console.log(i);
});
}
with setTimeout same result
for (let i = 1; i <= 100; i++) {
(function(z) {
setTimeout(
function(){console.log(z);},
z*1000
);
})(i);
}
for (let i = 1; i <= 100; i++) {
(function(z){
setTimeout(
function(){console.log(z);},
z*1000
);
})(i);
}
That is because you start all your Promises and setTimeouts()s simultaniously, their time will run out basically at the same time.
I see two solutions to your problem:
You could wait until a Promise runs out before continuing your code
You could add the delay of the previous setTimeout() to the next one's delay
Both solutions run asynchronously, which would free up the callstack for other tasks (which is important to do since JavaScript runs single-threaded). The first solution however is more elegant, and keeps your code more readable. That is why I will only go more in-depth into the first one.
For 1. to work, you need to wrap your code (or at least the asynchronous part) in an asynchronous body to be able to use the await keyword. We will use the await keyword in combination with a Promise and setTimeout() just like you used it, but we will wait for the Promise to be resolved.
In code, this could look like this:
Note: That wrapped function expression, which is immediately invoked, is called an IIFE.
function sleep(ms) {
return new Promise(res => setTimeout(res, ms));
}
(async function() {
for (let i = 1; i <= 100; i++) {
console.log(i);
await sleep(i*1000);
}
})();
I'm trying to add a sleep / delay function inside a js file, This one:
var webTest = function()
{
let regex = /^https?:\/\//;
let url = $('#list_urls').val().split('\n');
var xmlhttp = [], i;
var myObj2 = [], i;
for(let i = 0; i < url.length; i++)
{
(function(i) {
xmlhttp[i] = new XMLHttpRequest();
url[i] = url[i].replace(regex, '');
xmlhttp[i].open("GET", "https://website.com/API?key=<MY_API_KEY>&url="+url[i], false);
xmlhttp[i].onreadystatechange = function() {
if (xmlhttp[i].readyState === 4 && xmlhttp[i].status === 200) {
myObj2 = JSON.parse(xmlhttp[i].responseText);
document.getElementById("demo"+i).innerHTML = myObj2.results[1].categories;
}
};
xmlhttp[i].send();
})(i);
console.log(`The Server2: `+ myObj2);
}
}
I want this script to pause for 10 second and then again do work and then again pause for 10 second and do like this untill text length is greater thatn i in loop! My code works if i run for single time but it doesn't works if i run in loop because the website has rate limit in the api so that's why i'm trying to add a sleep function.
So what i've tried is await sleep(); method and also tried setTimeout method but it's not working as expected in sort it doesn't works at all with my code!
await sleep(); just doesn't works at all and displays msg like
Uncaught SyntaxError: await is only valid in async functions and async generators webTestfile.js:27
You can make use of ES6's async/await-feature!
To use await, it needs to be in a function/expression body declared async.
Basically, this will make your function be asynchronous, and make it wait for a Promise to be fulfilled. We make that Promise be fulfilled after a set delay using setTimeout().
Note that "after a set delay" does not mean "exactly after", it basically means "as early as possible after".
By doing this, the asynchronous function waits for the promise to be fulfilled, freeing up the callstack in the meantime so that other code can be executed.
The order of execution of this example is (simplified) as follows:
sleepingFunc() is placed on callstack
In iteration: await for Promise to be fulfilled, suspending this call 🡒 freeing up callstack
Place new calls on callstack
Eventually, Promise is fulfilled, ending await 🡒 place suspended call back on callstack
Repeat until sleepingFunc() finished
As you can see in step 3, if other calls take up more time than the delay, the suspended call will have to wait that extra time longer.
function sleep(ms) {
return new Promise(resolveFunc => setTimeout(resolveFunc, ms));
}
async function sleepingFunc() {
for (let i = 0; i < 5; ++i) {
console.log(i + " - from sleep");
await sleep(1000);
}
}
function synchronousFunc() {
for (let i = 0; i < 5; ++i) {
console.log(i + " - from sync");
}
}
sleepingFunc();
synchronousFunc();
This runs snippet runs one task every 1 second until the condition is satisfied, and then clears the timer.
const work = (i)=>{
console.log('doing work here ', i);
}
let counter = 0
const timer = setInterval(()=>{
if (timer && ++counter >= 10) {
clearInterval(timer)
}
work(counter);
}, 1000)
I'm new to the concept of recursion. I've been practicing JavaScript with some codes from javascript30.com. I've stumbled upon the below mention function:
function peep() {
const time = randomTime(200, 1000);
const hole = randomHole(holes);
hole.classList.add('up');
setTimeout(() => {
hole.classList.remove('up');
if (!timeUp) peep();
}, time);
}
Link to full code: https://codepen.io/luckyseven444/pen/bXqXbP (code is running ok in my PC)
Is it possible to form a simple loop rather than the recursive function peep() mentioned above? I mean I want to replace the second peep() inside setTimeout function.
Thanks
If you really insist, you can create an async function, wrap setTimeout with a Promise, await the Promise and add a loop:
async function test() {
for (let i = 0; i < 10; i++) {
console.log('before setTimeout', i);
await new Promise(resolve => setTimeout(() => {
console.log('timeout elapsed', i);
resolve();
}, 1000));
}
}
test();
I want to get data from db for several times. How to set a loop to execute getData() function in interval like 200ms. And if one of them success, rest of them won't be triggered. It's asynchronous method, and different from question here: Asynchronous Process inside a javascript for loop
for(var i = 0; i < 3; i++){
setTimeout(getData,200);}
This will end up with the output time interval is very close instead of 200ms, since they are asynchronous. Three "setTimeout" are triggered in a short time. like 0.001s 0.002s 0.003s, the output time is 0.201, 0.202, 2.203.
getData() returns a promise. But it can be normal function as long as it works.
You can do this by waiting for the setTimeout to finish before executing the next setTimeout
I don't believe this is possible with callbacks, as is the case with setTimeout, so you should transform it into a promise-based call
const promiseSetTimeout = timeout => new Promise(r => setTimeout(r, timeout));
const waitManyTimes = async () => {
for(let i = 0; i < 3; i++) {
await promiseSetTimeout(200);
// do something here, like getDB
console.log(i);
}
}
waitManyTimes();
Don't use a loop. Have the function call setTimeout() to run itself again if it fails.
var i = 0;
function callGetDB() {
getDB().then(db => {
// use DB
}).catch(() => {
if (i++ < 3) {
setTimeout(callGetDB, 200);
}
});
}
I'm assuming the asynchronous function getDB() returns a promise.
Using async/await:
let sleep = ms => new Promise(r => setTimeout(r, ms));
let main = async() => {
for(var i = 0; i < 3; i++) {
let db = getDB();
if (db)
return db;
await sleep(200);
}
};
This question already has answers here:
JavaScript ES6 promise for loop
(9 answers)
Closed 4 years ago.
function promise1 (num) {
return new Promise(resolve1 => {
let timeout = Math.random() * 5000
setTimeout(() => {
console.log(num)
resolve1()
}, timeout)
})
}
let promiseVar = promise1(0)
for (let i = 1; i < 5; i++) {
promiseVar.then(() => {
promiseVar = promise1(i)
})
}
I've got a function that creates a promise that might take an arbitrary amount of time to complete but I want the promises executed in a specific order. Inside the for loop I expect it to only begin the next promise after the previous one has resolved but the console logs the numbers in a random order as if it starts each promise before the last one has resolved. Is there a better way to execute a series of promises like this or have I overlooked something.
Try something like this:
function promise1 (num) {
return new Promise(resolve1 => {
let timeout = Math.random() * 5000
setTimeout(() => {
console.log(num)
resolve1()
}, timeout)
})
}
function runNext(i, max) {
if (i > max) return Promise.resolve(true);
return promise1(i).then(() => runNext(i+1));
}
runNext(0,4);
Or make it really easy on yourself and use async/await
(async () => {
for (let i = 0; i < 5; i++) {
await promise1(i);
}
})();
You can run all promises at the same time (if the order of rejecting/resolving promise doesn't matter) with promise.all. Also there is promise chaining when there is need to be sure that first in order must be resolved.
You can set promiseVar to the promise that results from then() in the loop. This will have the effect of changing the promises:
function promise1(num) {
return new Promise(resolve1 => {
let timeout = Math.random() * 1000
setTimeout(() => {
console.log(num)
resolve1()
}, timeout)
})
}
let promiseVar = promise1(0)
for (let i = 1; i < 5; i++) {
promiseVar = promiseVar.then(() => promise1(i))
}
This will create all the promises, but it will leave the last one without a then. You can use promiseVar.then() outside the loop to know when the last promise has resolved.