I need to scroll down before doing some action. my promise function is not waiting in await line. how can I solve this problem?
let scrollingPromise = new Promise(async (resolve, reject) => {
// I need this part to be done before resolving
await page.evaluate(() => {
const scrollingWindow = document.querySelector('.section-layout.section-scrollbox.scrollable-y.scrollable-show');
var scrollCount = 0;
function scrollFunction(){
setTimeout(()=>{
scrollingWindow.scrollBy(0, 5000);
scrollCount++;
if(scrollCount < 5){
scrollFunction();
}
}, 3000);
};
scrollFunction();
});
// but it resolves instantly doesn't wait for previous await
resolve();
});
//this .then() runs before my scrolling
scrollingPromise.then(async () => {
// ...
}
You're mixing await and Promise syntaxes. You're awaiting an asynchronous function that doesn't return a Promise, so it can't work. I believe you're trying to do this :
let scrollingPromise = new Promise((resolve, reject) => {
page.evaluate(() => {
const scrollingWindow = document.querySelector('.section-layout.section-scrollbox.scrollable-y.scrollable-show');
var scrollCount = 0;
function scrollFunction() {
setTimeout(() => {
scrollingWindow.scrollBy(0, 5000);
scrollCount++;
if (scrollCount < 5) {
scrollFunction();
} else {
resolve() // <-- Done, resolve here
}
}, 3000);
};
scrollFunction();
});
});
Related
Trying to learn proper async/await JavaScript to run functions in sequence when an early function in the sequence would be delayed (using setTimeout to simulate). I'm not getting the expected results (still getting "first", "second", "this should run first?" - see code).
What am I missing? Do I have the wrong idea about this?
Thanks in advance!
const zeroFunction = () => {
setTimeout(() => {
return new Promise((resolve) => {
console.log("This should run first?");
resolve();
});
}, 2000)}
const firstFunction = () => {
return new Promise((resolve) => {
console.log("first");
resolve();
})
}
const secondFunction = () => {
return new Promise((resolve) => {
console.log("second");
resolve();
})
}
async function fnAsync() {
await zeroFunction();
await firstFunction();
secondFunction();
}
fnAsync();
zeroFunction is currently returning undefined implicitly, not a Promise. Inverse the wrapping of the setTimeout and Promise constructor and it should work as expected.
const zeroFunction = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log("This should run first?")
resolve()
}, 2000)
})
}
const firstFunction = () => {
return new Promise((resolve) => {
console.log("first")
resolve()
})
}
const secondFunction = () => {
return new Promise((resolve) => {
console.log("second")
resolve()
})
}
async function fnAsync() {
await zeroFunction()
await firstFunction()
secondFunction()
}
fnAsync()
I am attempting a basic concept that is still eluding me...
In the option (that is commented out) including the Start().then... I'm able to nest the functions so that they start and end in the desired order.
In the await version, they start & end in the appropriate order but I'm not clear how I'm meant to put in log the resolve text after each one has completed. Sorry this is basic...
console.log("Synchronous result.");
function Start() {
return new Promise(function (resolve) {
console.log(`Starting the Start`);
setTimeout(() => resolve("Start has finished"), 5000);
});
}
function Middle() {
return new Promise(function (resolve) {
console.log(`Starting the Middle`);
setTimeout(() => resolve("Middle has finished"), 2000);
});
}
function End() {
return new Promise(function (resolve) {
console.log(`Starting the End`);
setTimeout(() => resolve("End has finished"), 1000);
});
}
// this works in the traditional promise method
/*
Start().then((result) => {
console.log(result),
Middle().then((result) => {
console.log(result),
End().then((result) => {
console.log(result);
});
});
});
*/
// now trying async/await
async function workflow() {
let call1 = await Start();
let call2 = await Middle();
let call3 = await End();
}
workflow();
Well, you almost have it. In an async function, the await will return the result of the promise. So all you have to do is do the console.log after.
console.log("Synchronous result.");
function Start() {
return new Promise(function (resolve) {
console.log(`Starting the Start`);
setTimeout(() => resolve("Start has finished"), 5000);
});
}
function Middle() {
return new Promise(function (resolve) {
console.log(`Starting the Middle`);
setTimeout(() => resolve("Middle has finished"), 2000);
});
}
function End() {
return new Promise(function (resolve) {
console.log(`Starting the End`);
setTimeout(() => resolve("End has finished"), 1000);
});
}
// this works in the traditional promise method
/*
Start().then((result) => {
console.log(result),
Middle().then((result) => {
console.log(result),
End().then((result) => {
console.log(result);
});
});
});
*/
// now trying async/await
async function workflow() {
let call1 = await Start();
console.log(call1);
let call2 = await Middle();
console.log(call2);
let call3 = await End();
console.log(call3);
}
workflow();
The resolve method of the new Promise you can imagine as a returnvalue. In this case you returning strings, what gets assigned to the variables call1 call2 call3. You can resolve any valid javascript data structure.
// now trying async/await
async function workflow() {
let call1 = await Start();
console.log("call1: ", call1);
let call2 = await Middle();
console.log("call2: ", call2);
let call3 = await End();
console.log("call3: ", call3);
}
workflow();
As you get a bit more hands on, you can also discover the Promise.all() and Promise.allSettled().
The async/await is the moder way of Promiseusage. Keep it like this.
await XXX evaluates to be the resolved value of the promise XXX.
So the variables you've named callX contain the resolved values.
console.log("Synchronous result.");
function Start() {
return new Promise(function (resolve) {
console.log(`Starting the Start`);
setTimeout(() => resolve("Start has finished"), 5000);
});
}
function Middle() {
return new Promise(function (resolve) {
console.log(`Starting the Middle`);
setTimeout(() => resolve("Middle has finished"), 2000);
});
}
function End() {
return new Promise(function (resolve) {
console.log(`Starting the End`);
setTimeout(() => resolve("End has finished"), 1000);
});
}
// this works in the traditional promise method
// now trying async/await
async function workflow() {
let call1 = await Start();
console.log({call1});
let call2 = await Middle();
console.log({call2});
let call3 = await End();
console.log({call3});
}
workflow();
I am bilding pet project in React, and faced an asynchronous problem. I have a promise chain,it works, but only once. Need to repeat it for a certain amount of time without stopping. I tried to wrap a promise with setInterval, but, it doesn't work as intended.What approach to use here?
let promise = new Promise((resolve) => {
setTimeout(() => {
resolve()
}, 3000);
}).then(() => {
props.changeBreathText('Exhalation')
}).then(() => {
setTimeout(() => {
props.changeBreathText('Inhale')
}, 4000);
})
you can't repeat a promise - it's a one-time thing, but you can duplicate the chain by wrapping it in a function - whenever you call a function a new chain will be created.
const props = {
changeBreathText: console.log
}
const delay = (time) => new Promise((resolve) => {
setTimeout(resolve, time)
})
/* with promises
const promiseChain = () =>
delay(3000)
.then(() =>
props.changeBreathText('Exhalation'))
.then(() => delay(4000))
.then(() => props.changeBreathText('Inhale')
);
function repeatChain(times, chain) {
let _chain = Promise.resolve();
for (let i = 0; i < times; i++) {
_chain = _chain.then(chain)
}
return _chain
}
*/
// with async await
async function promiseChain() {
await delay(3000)
props.changeBreathText('Exhalation')
await delay(4000)
props.changeBreathText('Inhale');
}
async function repeatChain(times, chain) {
for (let i = 0; i < times; i++) {
await chain();
}
}
repeatChain(3, promiseChain)
I'm using some Promises to fetch some data and I got stuck with this problem on a project.
example1 = () => new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo1');
}, 3000);
});
example2 = () => new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo2');
}, 3000);
});
doStuff = () => {
const listExample = ['a','b','c'];
let s = "";
listExample.forEach((item,index) => {
console.log(item);
example1().then(() => {
console.log("First");
s = item;
});
example2().then(() => {
console.log("Second");
});
});
console.log("The End");
};
If I call the doStuff function on my code the result is not correct, the result I expected is shown below.
RESULT EXPECTED
a a
b First
c Second
The End b
First First
Second Second
First c
Second First
First Second
Second The End
At the end of the function no matter how I try, the variable s gets returned as "", I expected s to be "c".
It sounds like you want to wait for each Promise to resolve before initializing the next: you can do this by awaiting each of the Promises inside an async function (and you'll have to use a standard for loop to asynchronously iterate with await):
const example1 = () => new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo1');
}, 500);
});
const example2 = () => new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo2');
}, 500);
});
const doStuff = async () => {
const listExample = ['a','b','c'];
for (let i = 0; i < listExample.length; i++) {
console.log(listExample[i]);
await example1();
const s = listExample[i];
console.log("Fisrt");
await example2();
console.log("Second");
}
console.log("The End");
};
doStuff();
await is only syntax sugar for Promises - it's possible (just a lot harder to read at a glance) to re-write this without async/await:
const example1 = () => new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo1');
}, 500);
});
const example2 = () => new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo2');
}, 500);
});
const doStuff = () => {
const listExample = ['a','b','c'];
return listExample.reduce((lastPromise, item) => (
lastPromise
.then(() => console.log(item))
.then(example1)
.then(() => console.log("Fisrt"))
.then(example2)
.then(() => console.log('Second'))
), Promise.resolve())
.then(() => console.log("The End"));
};
doStuff();
If you want NOT to wait for each promise to finish before starting the next;
You can use Promise.all() to run something after all your promises have resolved;
example1 = () => new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo1');
}, 3000);
});
example2 = () => new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo2');
}, 3000);
});
doStuff = () => {
const listExample = ['a','b','c'];
let s = "";
let promises = []; // hold all the promises
listExample.forEach((item,index) => {
s = item; //moved
promises.push(example1() //add each promise to the array
.then(() => {
console.log(item); //moved
console.log("First");
}));
promises.push(example2() //add each promise to the array
.then(() => {
console.log("Second");
}));
});
Promise.all(promises) //wait for all the promises to finish (returns a promise)
.then(() => console.log("The End"));
return s;
};
doStuff();
When I run the code, I get the error
mergePromise(...).then is not a function.
I want to know why I got this error.
const timeout = ms => new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, ms);
});
const ajax1 = () => timeout(2000).then(() => {
console.log('1');
return 1;
});
const ajax2 = () => timeout(1000).then(() => {
console.log('2');
return 2;
});
const ajax3 = () => timeout(2000).then(() => {
console.log('3');
return 3;
});
const mergePromise = ajaxArray => {
const data=[];
ajaxArray[0]().then(i=>data.push(i));
timeout(1005).then(() => {
ajaxArray[1]().then(i=>data.push(i));
});
timeout(10).then(() => {
ajaxArray[2]().then(i=>data.push(i));
});
return data;
};
I guess maybe the timeout function has some mistake. What am I doing wrong?
Maybe you can try return Promise.resolve(data) instead, it would return a promise, which is what you need.