睡眠()无法按预期工作

时间:2015-10-19 10:11:49

标签: javascript google-apps-script return delay sleep

在我的代码中,我尝试在继续执行其余代码之前尝试延迟一段时间。很基本的。我使用自定义睡眠功能,因为javascript的原生睡眠功能根本不起作用。我实际上是在谷歌电子表格中的应用程序脚本中工作,所以也许这就是原因。但是以下代码位于电子表格应用程序脚本中html文件的<script>标记中。

无论如何,当我使用sleep()时,它正在setTimeout

之前执行
function get_ids(db){

    window.alert("before window.ids is saved?");
    google.script.run.withSuccessHandler(getIdsFromAppscript).getIdsFromModel(db); 
    //this returns a result to getIdsFromAppscript but the following code doesn't wait 
    //for the result to be returned so I want to use sleep before the ids 
    //variable is returned by get_ids


    setTimeout(function(){
        window.alert("checking if ids is saved after 10s?");
        window.alert("In timeout ids="+window.ids);
        var ids= window.ids; //is non empty
    },10000);

    sleep(10000);

    var ids= window.ids;
    window.alert("after wait");
    window.alert("after sleep ids="+ids); //is empty but should be non empty

    return ids; //=window.ids , Need to return a non-empty result

}

function getIdsFromAppscript(result){
window.ids=result;

}

和睡眠功能:

function sleep(ms) {
  var start = new Date().getTime(), expire = start + ms;
  while (new Date().getTime() < expire) { }
  return;
}

当前输出顺序基于window.alert()

1) before window is saved?
2) after sleep
3) after sleep ids=  //basically empty which shouldn't be the case
4) checking if ids is saved after 10s?
5) In timeout ids= [.....] //non empty list

但是,所需的输出顺序是:

1) before window is saved?
2) checking if ids is saved after 10s?
3) In timeout ids= [.....] //non empty list
4) after sleep
5) after sleep ids= [...] //should be a non empty list 

我写setTimeout的原因是为了表明10秒后,结果存储在window.ids中,但即使在我睡了10秒甚至30秒后,我也可以#39;从window.ids获取结果。

我到底错在了什么?提前谢谢〜

3 个答案:

答案 0 :(得分:3)

Java Script,尤其是通过V8引擎无法入睡。睡眠导致JavaScript运行的整个线程停止,这打破了异步的整个点。 setTimeout()只等待你投入的时间内运行你推入的功能。它并没有停止其余的执行,无论先发生什么事都会先发生。

如果对您来说重要的是,按顺序发生某些事情,那么您需要使用回调或承诺。

代码中的一个例子可能是:

function doTimeout(ms) {
    setTimeout(function(){
      window.alert("checking if ids is saved after 10s?");
      window.alert("In timeout ids="+window.ids);
      var ids= window.ids; //is non empty
    },ms);
}

function sleep(ms, callback) {
  var start = new Date().getTime(), expire = start + ms;
  while (new Date().getTime() < expire) { }
  callback(ms);
}

sleep(10000, doTimeout);

答案 1 :(得分:1)

Javascript是单线程的。您必须从代码返回其他线程中的脚本才能执行。其他线程中的脚本包括处理超时事件的函数,保留或失败时调用的函数,以及使用XMLHttpRequest对象为异步请求提供的回调函数。

编写一个函数并将其调用sleep()不会改变这一点。您可以将它waitingForGodot()称为它所能产生的所有差异。你提供的代码所做的是在被调用的线程中花费大量的时间循环。它不会放弃控制并阻止所有其他脚本执行。如果它持续的时间足够长,我的浏览器会问我是否要中止(如你的)脚本。

答案 2 :(得分:0)

我在下面列出了两个示例,显示您的睡眠功能会阻止整个Javascript引擎。当我使用sleep函数时,即使我设置了100 ms的间隔并且输出延迟了10秒,也不会执行间隔功能。但是,在第二个示例中,输出会立即以正确的间隔打印。这表明您的sleep函数正在阻止整个执行引擎,这解释了您的ids数组为空的原因。

function sleep(ms) {
  var start = new Date().getTime(),
    expire = start + ms;
  while (new Date().getTime() < expire) {}
  return;
}

function get_ids() {

  document.write("before window.ids is saved?" + "<br>");

  var counter = 0;


  setInterval(function() {
    while (counter < 100) {
      document.write("checking if ids is saved after 10s?" + "<br>");
      counter = counter + 1
    }
  }, 100);

  sleep(10000);

  documen.write("after wait");

}

document.write("Start");

get_ids()

document.write("End");

在这个例子中,我已经注释了你的睡眠功能,正如预期的那样,输出每100毫秒打印一次:

function sleep(ms) {
  var start = new Date().getTime(),
    expire = start + ms;
  while (new Date().getTime() < expire) {}
  return;
}

function get_ids() {

  document.write("before window.ids is saved?" + "<br>");

  var counter = 0;

  setInterval(function() {
    while (counter < 100) {
      document.write("checking if ids is saved after 10s?" + "<br>");
      counter = counter + 1
    }
  }, 100);
  //sleep(10000);

  documen.write("after wait");

}

document.write("Start");

get_ids()

document.write("End");