This question already has answers here:
Combination of async function + await + setTimeout
(17 answers)
Closed 9 months ago.
I've the following code that should have to works for a slider:
let timeOut, timeOut2;
over = 1;
let back = 0;
setInterval(change2, 8000);
async function change2() {
innerFront = slides[over];
innerBack = slides[back];
await setTimeout(change, 8000);
innerFront.querySelectorAll('figure')[0].classList.remove('isActive');
innerFront.classList.remove('slideshow__inner--front');
innerBack.querySelectorAll('figure')[0].classList.remove('isActive');
innerBack.classList.remove('slideshow__inner--back');
over -= 1;
if (over < 0) over = slides.lenght;
back = over - 1;
if (back < 0) back = slides.lenght;
slides[over].classList.add('slideshow__inner--front');
slides[back].classList.add('slideshow__inner--back');
}
function change() {
return new Promise(function(resolve, reject) {
innerFront.querySelectorAll('figure')[0].classList.add('isActive');
timeOut2 = setTimeout(()=> {
innerBack.querySelectorAll('figure')[0].classList.add('isActive');
}, 1000);
resolve();
});
}
My problem consists in the fact that the 'change' function seems not to be performed despite the Await for Promise. In fact, the subsequent instructions are immediately performed, and obviously this generate errors.
I still have doubts about the promises, which I am studying, and here I think there can be something conceptual.
Does anyone have the patience to explain to me where I'm wrong?
There's a typo inside of change2() you wrote lenght instead of length twice.
Related
This question already has answers here:
How to make a promise from setTimeout
(8 answers)
How to handle multiple async requests?
(2 answers)
Closed 6 months ago.
this is regarding async await and promises. I am not very good at this so I guess i´m missing something. My code is meant to execute the first greetings function which it does. But then only once its done (and only then) it should execute any consecutive functions.
I have tried setting it up in many ways but either the second function doesn't execute or it executes before completion of the first.
Here is my code:
const greetingDivs = [firstDiv, secondDiv, thirdDiv, fourthDiv, fifthDiv]
let y = 0
function greetings() {
if (y != greetingDivs.length) {
setTimeout(() => {
consoleOutput.appendChild(greetingDivs[y])
y++
}, 500)
setTimeout(() => {
greetings()
}, 500)
}
if (y == greetingDivs.length) {
return console.log('Greetings are done!')
}
}
function secondFunction() {
console.log('I have waited')
}
async function consoleOn() {
const result = await greetings()
if (result) {
secondFunction()
}
}
consoleOn()
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)
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.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
The community is reviewing whether to reopen this question as of 9 days ago.
I just want to get the return value from setTimeout but what I get is a whole text format of the function?
function x () {
setTimeout(y = function () {
return 'done';
}, 1000);
return y;
}
console.log(x());
You need to use Promises for this. They are available in ES6 but can be polyfilled quite easily:
function x() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('done!');
});
});
}
x().then((done) => {
console.log(done); // --> 'done!'
});
With async/await in ES2017 it becomes nicer if inside an async function:
async function() {
const result = await x();
console.log(result); // --> 'done!';
}
You can't get a return value from the function you pass to setTimeout.
The function that called setTimeout (x in your example) will finish executing and return before the function you pass to setTimeout is even called.
Whatever you want to do with the value you get, you need to do it from the function you pass to setTimeout.
In your example, that would be written as:
function x () {
setTimeout(function () {
console.log("done");
}, 1000);
}
x();
Better to take a callback for function x and whatever task you want to perform after that timeout send in that callback.
function x (callback) {
setTimeout(function () {
callback("done");
}, 1000);
}
x(console.log.bind(console)); //this is special case of console.log
x(alert)
You can use a combination of Promise and setTimeOut like the example below
let f1 = function(){
return new Promise(async function(res,err){
let x=0;
let p = new Promise(function(res,err){
setTimeout(function(){
x= 1;
res(x);
},2000)
})
p.then(function(x){
console.log(x);
res(x);
})
});
}
I think you want have flag to know event occured or no. setTimeout not return a value. you can use a variable to detect event occured or no
var y="notdone";
setTimeout(function () {
y="done";
}, 1000);
You can access variable y after timeout occured to know done or not
I'm a bit confused as to how setTimeout works. I'm trying to have a setTimeout in a loop, so that the loop iterations are, say, 1s apart.
Each loop iteration makes an HTTP request and it seems like the server on the other end can't handle that many requests in such a short time span.
for (var i = 1; i<=2000 && ok; i++) {
var options = {
host:'www.host.com',
path:'/path/'+i
};
setTimeout(makeRequest(options, i), 1000);
};
Why does this not work and how can I achieve this?
Thank you
setTimeout is non blocking, it is asynchronous. You give it a callback and when the delay is over, your callback is called.
Here are some implementations:
Using recursion
You can use a recursive call in the setTimeout callback.
function waitAndDo(times) {
if(times < 1) {
return;
}
setTimeout(function() {
// Do something here
console.log('Doing a request');
waitAndDo(times-1);
}, 1000);
}
Here is how to use your function:
waitAndDo(2000); // Do it 2000 times
About stack overflow errors: setTimeout clear the call stack (see this question) so you don't have to worry about stack overflow on setTimeout recursive calls.
Using generators (io.js, ES6)
If you are already using io.js (the "next" Node.js that uses ES6) you can solve your problem without recursion with an elegant solution:
function* waitAndDo(times) {
for(var i=0; i<times; i++) {
// Sleep
yield function(callback) {
setTimeout(callback, 1000);
}
// Do something here
console.log('Doing a request');
}
}
Here is how to use your function (with co):
var co = require('co');
co(function* () {
yield waitAndDo(10);
});
BTW: This is really using a loop ;)
Generator functions documentation.
You need something like this
var counter = 5;
function makeRequst(options, i) {
// do your request here
}
function myFunction() {
alert(counter);
// create options object here
//var options = {
// host:'www.host.com',
// path:'/path/'+counter
//};
//makeRequest(options, counter);
counter--;
if (counter > 0) {
setTimeout(myFunction, 1000);
}
}
See also this fiddle
At the point of the alert(count); you can do your call to the server.
Note that the counter works opposite (counting down). I updated with some
comments where to do your thing.
Right now you're scheduling all of your requests to happen at the same time, just a second after the script runs. You'll need to do something like the following:
var numRequests = 2000,
cur = 1;
function scheduleRequest() {
if (cur > numRequests) return;
makeRequest({
host: 'www.host.com',
path: '/path/' + cur
}, cur);
cur++;
setTimeout(scheduleRequest, 1000)
}
Note that each subsequent request is only scheduled after the current one completes.
I might be late at the party but here is another (more readable) solution without the need to omit for loop.
What your code does is creating 2000 (actually 1999) setTimeout objects that will call the makeRequest function after 1 second from now. See, none of them knows about the existence of the other setTimeouts.
If you want them 1 sec apart from each other, you are responsible for creating them so.
This can be achieve by using your counter (in this case i) and the timeout delay.
for (var i = 1; i<=2000 && ok; i++) {
var options = {
host:'www.host.com',
path:'/path/'+i
};
setTimeout(makeRequest(options, i), i * 1000); //Note i * 1000
};
The first timeout object will be set for 1 second from now and the second one will be set for 2 seconds from now and so on; Meaning 1 second apart from each other.
I'm surprised that no one has mentioned this above, but it sounds like you need setInterval not setTimeout.
vat poller = setInterval(makeRequestFunc, 3000)
The code above will make a request every 3 seconds. Since you saved the object to the variable poller, you can stop polling by clearing the object like so:
cleanInterval(poller)
You're calling makeRequest() in your setTimeout call - you should be passing the function to setTimeout, not calling it, so something like
setTimeout(makeRequest, 1000);
without the ()
let i = 20;
let p = Promise.resolve(i)
while (i > 0) {
(i => {
p = p.then(() => {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log(i);
resolve()
}, 2000)
})
})
})(i)
i--
}
p = p.then(data => console.log('execution ends'))
I'm very late on the subject (as usual ...;) but the only way I found to loop requests to a slow time response API and getting responses without HTTP 504 is using promises.
async function LoadDataFromAPI(myParametersArray) {
for(var i = 0; i < myParametersArray.length; i++) {
var x = await RunOneRequest(myParametersArray[i]);
console.log(x); // ok
}
}
The function called by the async function :
function RunOneRequest(parameter) {
return new Promise(resolve => {
setTimeout(() => {
request(parameter, (error, response, body) => {
// your request
});
resolve('ok);
}, 2000); // 2 secs
});
}