Wait for an element to load javascript [duplicate] - javascript

This question already has answers here:
How to wait until an element exists?
(26 answers)
How to execute javascript code after an element is created without jquery?
(2 answers)
How do I add a delay in a JavaScript loop?
(32 answers)
Closed 1 year ago.
I am interacting with the webpage through chrome extension. I want to wait until an element (like a popup) comes up before continuing the interaction. I want to stop the execution of the function until the element appears because I am doing interacting in a sequential flow.
Below is the example function I created. This function is not working as intended. It only delays the first iteration of the loop and the rest of the iterations of the loop are instant. So, the max time this function wait is 100ms as of now. How can I either fix this function or define an elegant way to wait.
function waitUntilElementLoad(elem, maxWaitInSec) {
for (let i = 0; i < maxWaitInSec *10; i++) {
if(elem) { return true;}
setTimeout(() => {console.log(i);}, 100);
}
return false;
}
Attempt2: (Following up on comments and answers)
async function waitUntilElementLoad(elem, maxWait) {
for (let i = 0; i < maxWait*10; i++) {
if(elem) { return true;}
console.log(i);
await timer(100); // then the created Promise can be awaited
}
return false;
}
if (await waitUntilElementLoad(popUpElemNextButton, 5)) {
console.log("Popup button appeared")
} else {
console.log("Popup button not appeared")
}
The waitUntilElementLoad function returns false even if the elements load up in 1 sec and the waiting time is 5 sec. If the element is already there before calling the function. it returns true. Could it be that the function does not receive updated DOM during its processing? Is there a way to handle this?

Instead of using a loop, just call setTimeout when the element is not found.
function waitUntilElementLoad(selector, delay) {
if(document.querySelector(selector) != null){
// element found; do something
} else setTimeout(()=>waitUntilElementLoad(selector, delay), delay);
}

Related

How to stop a for loop inside a function with a button? [duplicate]

This question already has answers here:
Stop for loop using break on click
(5 answers)
Closed 5 months ago.
I want my program to generate a random number and multiply it with a number that a user inputs. Then take the result and multiply that with the user inputted number. This part works but how do I stop the loop with a button?
The loop is inside of a function and I want to use a button to stop the for loop. I used setTimeout to delay each result by 1.5 seconds. I tried to use set Interval on the function start but that didn't seem to work.
Here is an example using a recursive setTimeout pattern. It's not very pretty but should be enough for you to work on:
var stopLoop = false;
function start(i) {
stopLoop = false;
loop(i);
}
function stop() {
stopLoop = true;
}
function loop(i) {
if (stopLoop) {
stopLoop = false;
} else {
setTimeout(function() {
doWork(i);
});
}
}
function doWork(i) {
document.getElementById("display").innerHTML = i++;
loop(i);
}
<button onclick="start(0);">
Start Loop
</button>
<button onclick="stop();">
Stop Loop
</button>
<div id="display"></div>

Javascript loop only runs once [duplicate]

This question already has answers here:
How do I add a delay in a JavaScript loop?
(32 answers)
Closed 2 years ago.
Trying to make a react native app that takes text as input and converts it to morse code, using the phone's torch. I can get the translated morse code but when I try to convert that to light using the torch, the loop only runs once (There is a short flash) and then exits. Why is that happening/how do I fix that?
var j;
for(j = 0; j < cipher.length; j++) {
if(cipher[j] == '.') {
Torch.switchState(true);
setTimeout(function(){Torch.switchState(false)},200);
setTimeout(function(){},200);
}
else if(cipher[j] == '-') {
Torch.switchState(true);
setTimeout(function(){Torch.switchState(false)},600);
setTimeout(function(){},200);
}
else if(cipher[j] == ' ') {
setTimeout(function(){},600);
}
else {
setTimeout(function(){},1400);
}
}
The setTimeout() function needs a callback function to work. I guess that if you put the "if" conditionals into the callback functions it will work. I'll leave a example down here:
HTML:
<p>Live Example</p>
<button onclick="delayedAlert();">Show an alert box after two seconds</button>
<p></p>
<button onclick="clearAlert();">Cancel alert before it happens</button>
Javascript:
var timeoutID;
function delayedAlert() {
timeoutID = window.setTimeout(window.alert, 2*1000, 'That was really slow!');
}
function clearAlert() {
window.clearTimeout(timeoutID);
}
Another possibility is to use an anonymous function to call your callback, but this solution is a bit more expensive. Example:
var intervalID = setTimeout(function() { myFunc('one', 'two', 'three'); }, 1000);
Checkout the Official Guides in: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout

javascript loop with delay code fix [duplicate]

This question already has answers here:
How do I add a delay in a JavaScript loop?
(32 answers)
Closed 6 years ago.
how to fix this code as per
How do I add a delay in a JavaScript loop?.
it still gets executed without delay .
const spkz = responsiveVoice.speak;
let azj = ['hi', 'hello', 'how are ya'];
var i = 1; // set your counter to 1
function myLoop() { // create a loop function
azj.forEach((item, index) => {
setTimeout(() => { // call a 3s setTimeout when the loop is called
alert(item); // your code here
i++; // increment the counter
if (i < index) { // if the counter < 10, call the loop function
myLoop(); // .. again which will trigger another
} // .. setTimeout()
}, 10000)
})
}
myLoop();
You can't "pause" javascript like that. a setTimout is asynchronous, meaning it will not block synchronous code from running, so when you run any kind of "for" loop, it will call all the setTimeouts at once.
You can make a manual loop like this and delay it with recursion:
let azj = ['hi', 'hello', 'how are ya'];
var i = 0;
function myLoop() {
setTimeout(function() {
console.log(azj[i])
i++
if (i < azj.length) {
myLoop()
}
}, 3000)
}
myLoop();
For more information, check out this answer.
You don't have to use forEach inside the loop function. Instead, you can access the array items using azj[i]

For Loop never executing (Javascript / Jquery) [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 6 years ago.
So the for loop runs if I replace$.get('/preceed_with_an.txt', function(data){var ans = data.split('\n')}); with ans = ["filler","more filler"] but when the $.get line is in it refuses to execute the for loop and nothing is ever written to the console. For context, I am writing code that tells you if you should use A or AN before a word. Words that you use an for are all on separate lines in preceed_with_an.txt I have checked an the $.get functions and the file is written to the array just fine.
$(document).on('input',$('#givenWord'),function(){
var ans = new Array;
$.get('/preceed_with_an.txt', function(data){var ans = data.split('\n')});
for (var i = 0; i < ans.length; i++){
console.log("help");
if (ans[i] == $('#givenWord').lower){
var answer = $("#answer");
console.log("AN");
$(answer).text("An");
break;
}else{
var answer = $("#answer");
console.log("A")
$(answer).text("A");
}
}
});
The get() is asynchronous, so ans.length is equal to zero because the data return after the for loop execution.
You have to execute the for loop in the get() callback function:
$.get(url, function(data) {
var arr = data.split(',');
for(...) {
//...
}
});
Execution flow (your code)
Create ans array
Call the get() function
Try to execute the for loop (without available data)
get() return the data
Asynchronous call
Create ans array
Call the get() function with the for loop in the callback
get() returns data and executes the callback --> for loop with data
EXAMPLE
Check the console for the results. Even if the setTimeout function is called before the console.log(), the code continued the execution and waited for the callback's answer (after 1 second). When the result came out, the callback executed:
var def = $.Deferred();
def.done(function(data) {
console.log(data);
});
//Asynchronus call (delays for 1 second)
setTimeout(function() {
def.resolve('Callback after 1 second')
}, 1000);
//Execute immediately
console.log('Write something!');
//Console results
// 1. Write something
// 2. callback (after 1 second)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Check these links about asynchronous functions:
jQuery.get()
Async

setTimeout and passing variables to anonymous function together [duplicate]

This question already has answers here:
setTimeout in for-loop does not print consecutive values [duplicate]
(10 answers)
Closed 8 years ago.
i'm writing a code and i've stuck with setTimeout function. I would like to get animation effect. Display elements of array with delay. Code is done.
for (var i=0;i <= array.length-1;i++) {
(function(el) {
setTimeout(function(){
document.getElementById('Result').innerHTML += Math.floor(el);
console.log(Math.floor(el));
}, 3000*(i+1));
})(array[i]);
I had problem with delay when i use for (var i=array.length-1; i>=0;i--) Why? (The idea of this code is display items array form the last to the first)
for (var i=0;i <= array.length-1;i++) {
(function(el) {
setTimeout(function(){
Give now the same resultat as: for (var i=array.length-1; i>=0;i--) {
console.log(array[i]+'!')
The problem here is about closures. A closure is a type of anonymous function used to remember the arguments for using them later in asynchronous code (e.g. in functions called by setTimeout).
If you write something like:
setTimeout(function(foo){...}(value), 3000)
the function gets called before calling setTimeout. You have to use a closure to do this:
(function(foo){
setTimeout(function() {
... do something with foo ...
}, 3000);
})(value_of_foo);
This code will remember the value of foo creating a setTimeout with a function that uses it.
Another problem is that you have to increase the setTimeout time to create a delay, otherwise the for will create a bunch of setTimeout(..., 3000) that will be executed all at once. So what you will need to do to your code is something like the following:
for (var i = 0; i <= array.length; i++) {
(function(el) {
setTimeout(function(){
document.getElementById('Result').innerHTML += Math.floor(el)
}, 3000 * i);
})(array[i]);
}
Timeouts don't execute until after your main function has finished, this means that by the time your timeout function executes per loop, your i variable will be at its final value (in this case = 0). Your function declaration is also incorrect as the timeout function does not pass in those parameters for you. To do this, you need to wrap your timeout inside of another function call that takes in the parameters for the current loop, try something like this instead...
for (var i=array.length-1; i>=0;i--) {
function(array, i) {
setTimeout(function() {
document.getElementById('Result').innerHTML += Math.floor(array[i]);
}, (i+1) * 3000);
}(array, i);
}
First of all you are immediately calling the function and its result is assigned as the callback of the timeout. (this is wrong as the first argument must be a function)
Then, you have some syntax errors with missing closing } and )..
Try
for (var i=array.length-1; i>=0;i--) {
function(array,i){
setTimeout(function(){
document.getElementById('Result').innerHTML += Math.floor(array[i]);
}, 3000*i);
}(array,i);
}
I used 3000*i so that each timeout is 3 seconds after the other

Categories

Resources