等到条件满足或在javascript中传递超时

时间:2018-03-01 16:49:18

标签: javascript sleep

我需要睡眠代码,直到满足某些条件或传递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();

6 个答案:

答案 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));
}