Reputation: 476
I currently have 5 functions; each one uses setInterval
to wait for an element to load and than clicks the element when it is available which leads to the next webpage. These functions also take place inside of a while
loop. It is very important that these functions take place one after another and the while
loop waits for all the functions to complete before looping again. Due to the functions being asynchronous the loop will run x
times before any of the functions can even load.
Example of what I am trying to do:
function one () {
var checkForItem = setInterval(function () {
if ($('#element').length) {
$('#element').click();
clearInterval(checkForItem);
}
}, 100);
}
Imagine 5 of these functions (one
, two
, three
, four
, five
), all with the same format using setInterval
and the following while
loop:
var x = 0, y = 10;
while (x < y){
one();
two();
three();
four();
five();
x++
}
How would I go about ensuring all the functions take place one after another before having the loop continue?
Note: I have tried using promises although due to the functions being async the loop still continues before the functions complete.
Upvotes: 3
Views: 7956
Reputation: 2149
Try wrap promise with async await:
async function one (){
await (new Promise(function(reolve, reject){
var checkForItem = setInterval(function () {
if ($('#element').length) {
$('#element').click();
clearInterval(checkForItem);
resolve();
}
}, 100);
}));
}
//And then in your while loop:
while (x < y){
await one();
await two();
...
x++
}
note: your while loop must be wrapped in an async function also.
Upvotes: -1
Reputation: 664206
Use async
/await
syntax with the promises:
function delay(t) {
return new Promise(resolve => setTimeout(resolve, t));
}
async function one() {
while (!$('#element').length) {
await delay(100);
}
$('#element').click();
}
async function main() {
for (var x = 0; x < 10; x++) {
await one();
await two();
await three();
await four();
await five();
}
}
Upvotes: 4
Reputation: 370639
Define the selectors in an array, and gradually iterate over the array in the interval, until the end of the array is reached:
const initialSelectorsToFind = ['#element1', '#element2', '#element3']; // add more as desired
const elementSelectorsToFind = Array.from({ length: 10 })
.reduce(arrSoFar => [...arrSoFar, ...initialSelectorsToFind], []);
let elementIndexToFind = 0;
function tryClick(){
const elementToFind = $(elementSelectorsToFind[elementIndexToFind]);
if (elementToFind.length) {
elementToFind.click();
elementIndexToFind++;
if (elementIndexToFind === elementSelectorsToFind.length) {
clearInterval(tryClickInterval);
}
}
}
const tryClickInterval = setInterval(tryClick, 100);
But if you're trying to trigger a function (such as something that clicks an element) when an element gets added to the DOM, it would be far better off to use something that triggers when the add occurs, such as a callback in the creator function, or MutationObserver
Upvotes: 0