代码执行中的同步延迟

时间:2011-08-03 05:07:28

标签: javascript jquery settimeout

我有一个代码需要在延迟说5000 ms后执行。目前我使用的是setTimeout但它是异步的,我希望执行等待它的返回。我尝试过使用以下内容:

function pauseComp(ms) 
 {
     var curr = new Date().getTime();
     ms += curr;
     while (curr   < ms) {
         curr = new Date().getTime();
     }
 } 

但是我想延迟的代码是使用raphaeljs绘制一些对象,并且显示不是很平滑。我正在尝试使用doTimeout插件。我只需要延迟一次,因为延迟和要延迟的代码都在循环中。我没有要求身份证,所以我没有使用它。 例如:

for(i; i<5; i++){ $.doTimeout(5000,function(){
         alert('hi');  return false;}, true);}

等待5秒钟,然后给出第一个Hi,然后连续循环迭代在第一个之后立即显示警报。我想要它做的是等待5秒再次提醒警报等待然后提供警报等等。

任何提示/建议都表示赞赏!

10 个答案:

答案 0 :(得分:42)

接受答案的变化与此一样好。

另外,我同意更喜欢setTimeout和异步函数调用的注意事项,但有时例如,在构建测试时,您只需要一个同步等待命令......

function wait(ms) {
    var start = Date.now(),
        now = start;
    while (now - start < ms) {
      now = Date.now();
    }
}

如果你想要它在几秒钟内,在while检查时将开始ms除以1000 ......

答案 1 :(得分:5)

JavaScript是一种单线程语言。您无法合并setTimeout和同步处理。会发生什么,计时器将会失效,但JS引擎将等待处理结果,直到当前脚本完成。

如果你想要同步方法,只需直接调用方法!

如果要在setTimeout之后处理某些内容,请将其包含在内或从超时函数中调用它。

答案 2 :(得分:4)

如果您想利用新的async / await语法,可以将set timeout转换为promise,然后等待它。

function wait(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("Done waiting");
      resolve(ms)
    }, ms )
  })
}  

(async function Main() {
  console.log("Starting...")
  await wait(5000);
  console.log("Ended!")
})();

答案 3 :(得分:2)

非超时循环(检查时间或计数到1000000或其他)只是锁定浏览器。 setTimeout(或$.doTimeout插件)是最佳方式。

在循环中创建超时将不起作用,因为循环不等待先前的超时在继续之前发生,如您所发现的那样。尝试更像这样的东西:

// Generic function to execute a callback a given number
// of times with a given delay between each execution
function timeoutLoop(fn, reps, delay) {
  if (reps > 0)
    setTimeout(function() {
                 fn();
                 timeoutLoop(fn, reps-1, delay);
               }, delay);
}

// pass your function as callback
timeoutLoop(function() { alert("Hi"); },
            5,
            5000);

(我只是快速地将它拼凑在一起,所以尽管我确信它有效,但它可以通过多种方式进行改进,例如,在“循环”中它可以将索引值传递给回调函数,以便您自己的代码知道它在哪个迭代。但希望它会让你开始。)

答案 4 :(得分:2)

我做了一个简单的同步超时功能。它以两种不同的方式工作,回调和非回调。

功能:

function wait(ms, cb) {
  var waitDateOne = new Date();
  while ((new Date()) - waitDateOne <= ms) {
    //Nothing
  }
  if (cb) {
    eval(cb);
  }
}

回调示例:

wait(5000,"doSomething();");

非回调示例:

console.log("Instant!");
wait(5000);
console.log("5 second delay");

答案 5 :(得分:2)

同步等待(仅用于测试!):

const syncWait = ms => {
    const end = Date.now() + ms
    while (Date.now() < end) continue
}

用法:

console.log('one')
syncWait(5000)
console.log('two')

异步等待:

const asyncWait = ms => new Promise(resolve => setTimeout(resolve, ms))

用法:

(async () => {
    console.log('one')
    await asyncWait(5000)
    console.log('two')
})()

备用(异步):

const delayedCall = (array, ms) =>
    array.forEach((func, index) => setTimeout(func, index * ms))

用法:

delayedCall([
    () => console.log('one'),
    () => console.log('two'),
    () => console.log('three'),
], 5000)

答案 6 :(得分:1)

使用新的Atomics API,您可以启动同步延迟而不会出现性能峰值:

const sleep = milliseconds => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds)

sleep(5000) // Sleep for 5 seconds

console.log("Executed after 5 seconds!")

答案 7 :(得分:0)

以下是如何使用JQuery doTimeout插件

jQuery('selector').doTimeout( [ id, ] delay, callback [, arg ... ] );

来自docs:“如果回调返回true, doTimeout 循环将在延迟后再次执行,创建一个轮询循环,直到回调为止返回非真值。

var start = Date.now();
console.log("start: ", Date.now() - start);
var i = 0;
$.doTimeout('myLoop', 5000, function() {
  console.log(i+1, Date.now() - start);
  ++i;
  return i == 5 ? false : true;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-dotimeout/1.0/jquery.ba-dotimeout.min.js"></script>

答案 8 :(得分:-1)

使用函数发生器的解决方案。证明它可以做到。 不推荐

function wait(miliseconds){

  const gen = function * (){
     const end = Date.now() + miliseconds;
     while(Date.now() < end){yield};
     return;
  }
  
  const iter = gen();
  while(iter.next().done === false);
}


console.log("done 0");
wait(1000);
console.log("done 1");
wait(2000);
console.log("done 2");

答案 9 :(得分:-1)

节点解决方案

使用fs.existsSync()进行延迟

const fs = require('fs');
const uuidv4 = require('uuid/v4');

/**
 * Tie up execution for at-least the given number of millis.  This is not efficient.
 * @param millis Min number of millis to wait
 */
function sleepSync(millis) {
    if (millis <= 0) return;
    const proceedAt = Date.now() + millis;
    while (Date.now() < proceedAt) fs.existsSync(uuidv4());
}

fs.existsSync(uuidv4())用于执行以下操作:

  1. 通过生成uuid并查找不存在的文件来占用线程
  2. 新的uuid每次都会破坏文件系统缓存
  3. 查找文件可能是一种优化的操作,应该允许其他活动继续进行(即不固定CPU)