I need to sleep the code until some condition is met or a 3 second timeout is passed. then return a simple string. Is there anyway I can do this?
// this function needs to return a simple string
function something() {
var conditionOk = false;
var jobWillBeDoneInNMiliseconds = Math.floor(Math.random() * 10000);
setTimeout(function() {
// I need to do something here, but I don't know how long it takes
conditionOk = true;
}, jobWillBeDoneInNMiliseconds);
// I need to stop right here until
// stop here until ( 3000 timeout is passed ) or ( conditionOk == true )
StopHereUntil( conditionOk, 3000 );
return "returned something";
}
here is what I exactly going to do:
I make the browser scroll to bottom of the page, then some ajax function will be called to fetch the comments (that I have not control on it). Now I need to wait until comments are appeared in document with ".comment" class.
I need the getComments() function return comments as a json string.
function getComments() {
window.scrollTo(0, document.body.scrollHeight || document.documentElement.scrollHeight);
var a = (document.querySelectorAll('div.comment'))
// wait here until ( a.length > 0 ) or ( 3 second is passed )
// then I need to collect comments
var comments = [];
document.querySelectorAll('div.comment p')
.forEach(function(el){
comments.push(el.text());
});
return JSON.stringify(comments);
}
getComments();
I came across this problem and none of the solutions were satisfactory. I needed to wait until a certain element appeared in the DOM. So I took hedgehog125's answer and improved it to my needs. I think this answers the original question.
const sleepUntil = async (f, timeoutMs) => {
return new Promise((resolve, reject) => {
const timeWas = new Date();
const wait = setInterval(function() {
if (f()) {
console.log("resolved after", new Date() - timeWas, "ms");
clearInterval(wait);
resolve();
} else if (new Date() - timeWas > timeoutMs) { // Timeout
console.log("rejected after", new Date() - timeWas, "ms");
clearInterval(wait);
reject();
}
}, 20);
});
}
Usage (async/await promise):
try {
await sleepUntil(() => document.querySelector('.my-selector'), 5000);
// ready
} catch {
// timeout
}
Usage (.then promise):
sleepUntil(() => document.querySelector('.my-selector'), 5000)
.then(() => {
// ready
}).catch(() => {
// timeout
});
You should be able to achieve this using Promise.race. Here's a basic example:
let promise1 = new Promise(resolve => {
setTimeout(resolve, 500, 'one');
});
let promise2 = new Promise(resolve => {
setTimeout(resolve, 800, 'two');
});
async function fetchAndLogResult() {
let result = await Promise.race([promise1, promise2]);
console.log(result);
}
fetchAndLogResult();
Here's an alternative version, more concise although not using async/await:
let promise1 = new Promise(resolve => {
setTimeout(resolve, 500, 'one');
});
let promise2 = new Promise(resolve => {
setTimeout(resolve, 800, 'two');
});
Promise.race([promise1, promise2]).then(result => console.log(result));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With