我需要睡眠代码,直到满足某些条件或传递3秒超时。然后返回一个简单的字符串无论如何我能做到吗?
// 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";
}
这就是我要做的事情:
我将浏览器滚动到页面底部,然后调用一些ajax函数来获取注释(我无法控制它)。现在我需要等到带有“.comment”类的文档中出现注释。
我需要getComments()
函数返回注释作为json字符串。
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();
答案 0 :(得分:2)
您应该可以使用Promise.race
实现此目的。这是一个基本的例子:
metadata("Copyright Notice", "John Smith");
metadata.copyright("John Smith");
metadata("Manufacturer", "Canon");
metadata.manufacturer("Canon");

这是一个替代版本,虽然不使用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();
/ async
但更简洁:
await

答案 1 :(得分:2)
我遇到了这个问题,没有一个解决方案令人满意。我需要等到某个元素出现在DOM中。所以我接受了hedgehog125的回答,并将其改进为我的需求。我认为这可以回答原始问题。
async function sleepUntil(f, timeoutMs) {
return new Promise((resolve, reject) => {
timeWas = new Date();
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);
});
}
用法:
await sleepUntil(() => document.querySelector('.my-selector'), 5000);
答案 2 :(得分:1)
在JavaScript中没有办法等待。您可以使用settimeout
,也可以使用while循环(请记住,在发生这种情况时脚本无法运行,然后页面可能会无响应)。
使用settimeout
// this function needs to return a simple string
function something() {
conditionOk = false;
var jobWillBeDoneInNMiliseconds = Math.floor(Math.random() * 10000);
timeout = 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 )
timeWas = new Date();
wait = setInterval(function() {
if (conditionOk) {
// Communicate what you were trying to return using globals
clearInterval(wait);
}
if (new Date() - timeWas > 3000) { // Timeout
// Clear this interval
clearInterval(wait);
}
}, 30);
}
随着
// this function needs to return a simple string
function something() {
conditionOk = false;
var jobWillBeDoneInNMiliseconds = Math.floor(Math.random() * 10000);
timeout = 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 )
timeWas = new Date();
while ((! conditionOk) && (! (new Date() - timeWas > 3000))) { // 3000 = the delay
// Do nothing
}
if (conditionOk) {
return "returned something";
}
else {
return "returned nothing";
}
}
您可能还想看看这个问题:JavaScript sleep/wait before continuing
希望这有帮助!
答案 3 :(得分:0)
好的,因为您使用的是ajax
,您可以执行以下操作:
var eventEmitter = new EventEmitter()
eventEmitter.on('myEvent', myFunction)
$.ajax(...).then(function() {
eventEmitter.emit('myEvent', {state: true})
})
setTimeout(function() { eventEmitter.emit('myEvent', {state: false}), 3000);
function myFunction() {
//you can do your checks inside here
}
你的ajax而不使用jQuery
:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'myservice/username?id=some-unique-id');
xhr.onload = function() {
if (xhr.status === 200) {
eventEmitter.emit('myEvent', {state: true})
}
else {
alert('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send();
答案 4 :(得分:0)
我在寻找类似的解决方案时,在浏览器中打开了这个问题。也许post author不再需要它了,但是这里还有其他来自非事件循环世界(php,java,python)的人。
这是我在阅读MDN之后得到的: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
这两个描述了所需的内容。您将需要一些辅助功能。它看起来肿,但在JS中似乎没有其他方法。虽然可以完成工作:)
// sleep helper
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
// func that will check your condition
function checkCondition(number) {
if (number == 5) return true;
else return false;
}
// helper that will wait and then check the condition
// await halts the execution flow until sleep is resolved
// this is the part that you need
async function waitOneSecondAndCheckCondition(number) {
const v = await sleep(500);
return checkCondition(number);
}
// since most likely you want to poll the checkCondition
// and not waste all the time waiting
// this polls conditon every half a second
// and in the end return a simple string
// either when condition is met or after three seconds
async function waitUntilConditionIsMetOrTimeoutIsPassed() {
for (let i = 0; i < 6; i++) {
let result = await waitOneSecondAndCheckCondition(i);
console.log("i is: " + i + " condition result is: " + result);
if (!result) continue;
else break;
}
}
waitUntilConditionIsMetOrTimeoutIsPassed();
如果在3秒钟内满足条件,则输出控制台输出:
i is: 0 condition result is: false
i is: 1 condition result is: false
i is: 2 condition result is: false
i is: 3 condition result is: true
a simple string
发生超时时控制台输出:
i is: 0 condition result is: false
i is: 1 condition result is: false
i is: 2 condition result is: false
i is: 3 condition result is: false
i is: 4 condition result is: false
i is: 5 condition result is: false
a simple string
希望这对像我这样的所有JS新手都有帮助:)
答案 5 :(得分:0)
如果你想等到某个条件满足:
main();
async function main() {
let foo = 0;
// for demo purposes, artificially increment foo
setInterval(() => foo++);
console.log('Waiting until foo reaches 1337 ...');
await until(() => foo === 1337);
console.log('foo === ' + foo);
}
function until(condition) {
return new Promise((resolve) => {
const interval = setInterval(() => {
if (condition()) {
clearInterval(interval);
resolve();
}
});
});
}
如果你想等到一定的时间过去:
main();
async function main() {
console.log('Waiting 2 seconds ...');
await milliseconds(2_000);
console.log('Done!');
}
function milliseconds(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}