function sleep(cb, ms) {
return new Promise((cb) => setTimeout(cb, ms));
}
async function delayedGreeting() {
console.log("Hello");
await sleep(myfun, 1000);
console.log("World!");
}
function myfun() {
console.log("whatever");
}
delayedGreeting();
console.log("Goodbye!");
Can someone please explain in the context of Eventloop, Callback Queue and Stack as to what is happening here as I don't see the word 'whatever' in the output. Is there a mistake in the code and if so what is it?
You forgot to add parenthesis for myfun function parameter on this line await sleep(myfun, 1000);.
DEMO
function sleep(cb, ms) {
return new Promise((cb) => setTimeout(cb, ms));
}
async function delayedGreeting() {
console.log("Hello");
await sleep(myfun(), 1000);
console.log("World!");
}
function myfun() {
console.log("whatever");
}
delayedGreeting();
console.log("Goodbye!");
There are some minor mistakes in the code. I am pointing them below.
You should write resolve in the Promise.
return new Promise((resolve) => resolve (setTimeout(()=>{cb()}, ms)));
If you want myfun to run after a timeout of 1000 millisecond, you must call the function in the settimeout first parameter. Like this,
setTimeout(()=>{cb()}, ms);
Here is the updated source code,
function sleep(cb, ms) {
return new Promise((resolve) => resolve (setTimeout(()=>{cb()}, ms)));
}
async function delayedGreeting() {
console.log("Hello");
await sleep(myfun, 1000);
console.log("World!");
}
function myfun() {
console.log("whatever");
}
delayedGreeting();
console.log("Goodbye!");
And the right output according to the implementation that you are trying the code should be like this,
Hello
Goodbye!
World!
whatever
You should try like this -
function sleep(cb, ms) {
return new Promise((resolve) => resolve(setTimeout(cb, ms)));
}
It seems you are overriding the cb value inside promise.
Related
I have multiple asynchronous functions that I want to execute one after the other however the next function is executing before the previous one has finished.
async function x() {
for (...) {
console.log("awaiting" + i)
function fooPromise() {
return new Promise(function(resolve) {
foo();
resolve();
});
}
await fooPromise();
console.log("awaited" + i)
}
}
async foo(){
for(...){
await sleep(1500);
}
console.log("finished");
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
The expected output should be:
awaiting1
finished
awaited1
awaiting2
finished
awaited2
awaiting3
finished
awaited3
but instead I'm getting:
awaiting1
awaited1
awaiting2
awaited2
awaiting3
awaited3
finished
finished
finished
I'm fairly new to using promises and async so any help would be appreciated.
return new Promise(function(resolve) {
foo();
resolve();
});
The code you pass to the promise constructor runs immediately and synchronously. The constructor is typically meant for taking code written using callbacks, and then wrapping the callback in a promise (as in your sleep example).
So this code will immediately call foo, ignore the promise returned by foo, and then immediately resolve the new promise. The fact that foo does things later makes no difference to this promise.
Since foo already returns a promise (because it's an async function), there's no need to wrap it in a new one. You can change your code to:
async function x() {
for (let i = 1; i <= 3; i++) {
console.log("awaiting" + i);
await foo();
console.log("awaited" + i);
}
}
async function foo() {
for(let i = 1; i <= 2; i++){
await sleep(1500);
}
console.log("finished");
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
x();
So i have a IIFE as such in my code with a while loop inide. When the loop finished the console.log("Hey") executes but it doesnt come out of the function. Can anyone tell me whats going on?
(function () {
return new Promise(async resolve => {
while (i <= fcount) {
i++;
//some code
}
console.log("Hey");
resolve("done");
})
}());
When you say
it doesn't come out of the function
Yes, it comes out of the function returning you a promise.
Just do something like this:
(function () {
return new Promise(resolve => {
while (i <= fcount) {
i++;
//some code
}
console.log("Hey");
resolve("done");
})
}().then(message => console.log(message)));
And you will get done in the console.
Another thing, why you use async you always need to use async with await.
You can do something like this:
async function whileFunc() {
const message = await (function () {
return new Promise(resolve => {
while (i <= fcount) {
i++;
//some code
}
console.log("Hey");
resolve("done");
})
}());
console.log(message);
}
calling whileFunc you will get message using async/await
I wasn't closing the browser before returning (using puppeteer), hence the program kept running. Thanks everyone for your feedback.
I read about async/await, but I've a critical question.
At first I explain an old example to show base of my question and then I ask my exact question.
Everybody know it:
console.log('1');
console.log('2');
console.log('3'); // Ex: 123
It is simple but in below case:
console.log('1');
setTimeout(()=>{
console.log('2');
},0);
console.log('3'); // Ex: 132
It is simple too, setTimeout function is asynchronous and JavaScript jump from it and after resolve run its function, so we see 2 after 1 and 3.
But, now I read async/await and I wrote a function like this:
(async function test() {
console.log('1');
await setTimeout(()=>{
console.log('2');
},0);
console.log('3');
})(); // Ex: 132
The Export is 132 too, why? this is my question, why 3 run before 2? I expect because of async/await after 1 JavaScript wait for 2 and then wrote 3. why 132?
await only suspends when the value passed to it is a Promise. In your case, setTimeout returns a Number so await doesn't wait for it.
The correct code will be as follows:
async function test() {
console.log('1');
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve()
}, 0);
});
console.log('3');
}
Because setTimeout doesn't return a promise. await x only waits if x is a promise; if x isn't a promise, it's (effectively) wrapped in one as though you had await Promise.resolve(x). That means the code following it will run asynchronously but as soon as possible.*
If you want a promise version of setTimeout, see this question's answers. But even with that, your test function wouldn't use a callback, instead you'd just await the promise-enabled timeout:
function later(delay) {
return new Promise(function(resolve) {
setTimeout(resolve, delay);
});
}
async function test() {
console.log("1");
await later(10);
console.log("2");
console.log("3");
}
test().catch(e => console.error(e));
console.log("After the call (just to prove it does wait for the timeout after 1 and before 2");
* On browsers, that's guaranteed to be before a setTimeout(..., 0) scheduled during the same task, because promise callbacks scheduled during a task occur just after the end of that task, before the next task is picked up from the queue (even if the next task was scheduled before the promise callback). More on this ("macrotasks" and "microtasks") in this question's answers.
You can await to that functions that returns Promise. setTimeout does not returns Promise. So in this case await used before the setTimeout does not has a sense.
You can wrap your setTimeout into a Promise and call resolve at the setTimeout function.
(async function test() {
console.log('1');
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve(); // also can pass a parameter here to get it via await.
},0);
});
console.log('3');
})();
I have a function that does some async work and returns a Promise, and I want to execute this function indefinitely until the promise is rejected.
Something like the following :
doSomethingAsync().
.then(doSomethingAsync)
.then(doSomethingAsync)
.then(doSomethingAsync)
// ... until rejection
I made a little CodePen so I can test potential solutions : http://codepen.io/JesmoDrazik/pen/pbAovZ?editors=0011
I found several potential answers but nothing seems to work for my case.
If anyone has a solution, I'd be glad, because I just can't find anything !
Thanks.
You can do
(function loop(){
doSomethingAsync().then(loop);
})();
But looking at your pen it's not clear where the rejection should come from. If you want to stop repeating an operation when the user clicks a button, you can change a state in the button handling and then do
(function loop(){
doSomethingAsync().then(function(){
if (!stopped) loop();
});
})();
Made a modification to your codepen
var FAKE_COUNT = 0;
function doSomething() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('doing something async: ' + FAKE_COUNT)
if (FAKE_COUNT < 10) {
resolve();
} else {
reject();
}
FAKE_COUNT ++;
}, 1000);
});
}
const button = document.querySelector('.js-button');
button.addEventListener('click', () => {
// maybe we can do something here ?
})
function test() {
doSomething().then(test).catch(() => {
console.log("Rejected")
});
}
test();
FAKE_COUNT just becomes the flag, so if you want to stop the promise with a click instead of a count you could just make it a bool and check that when executing the async task
Depending on where you want the logic and rejection to take place, but assuming you want the promise itself to be self executing (otherwise the asynchronous execution itself could loop) it could return itself as a new promise:
function doSomething() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('doing something async');
resolve();
}, 1000);
}).then(()=>doSomething());
}
For the rejection part, the easiest way would be to introduce a flag, (although that would make the promise a little less self containing):
var stop = false;
function doSomething() {
return new Promise((resolve, reject) => {
if(stop)
reject();
else{
setTimeout(() => {
console.log('doing something async');
resolve(); //(check for stop could be done here as well)
}, 1000);
}
}).then(()=>doSomething());
}
const button = document.querySelector('.js-button');
button.addEventListener('click', () => {
stop = true;
});
doSomething();
Considering code snippet below,
function one(){
var prm = new Promise(function(resolve,reject){
});
prm.customKey = function(){
}
return prm;
}
function two(){
return one().then(function(){
//something
});
}
Now calling the function two, returns a promise in which 'customKey' is missing
function three(){
return one();
}
But while doing the same thing in function three(without handling success using 'then'),
returns a promise which has 'customKey' in it.
Can someone clarify me whats really happening and why?
As you can see from "Mozilla Docs" then method returns new Promise (e.g: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then).
If you want to assign a function to retrieve / do something in resolve function do it like this:
var prm = new Promise((resolve, reject) => {
let customKeyFunction = () => {
console.log("I'm custom key function.");
};
resolve(customKeyFunction);
})
From now on you can call this function like that:
function two() {
return one().then(customKey => {
customKey();
})
}