Javascript 代码执行中的同步延迟
我有一个代码需要在一些延迟后执行,比如5000毫秒。目前我正在使用setTimeout,但它是异步的,我希望执行等待返回。我已尝试使用以下方法:Javascript 代码执行中的同步延迟,javascript,jquery,settimeout,Javascript,Jquery,Settimeout,我有一个代码需要在一些延迟后执行,比如5000毫秒。目前我正在使用setTimeout,但它是异步的,我希望执行等待返回。我已尝试使用以下方法: function pauseComp(ms) { var curr = new Date().getTime(); ms += curr; while (curr < ms) { curr = new Date().getTime(); } } 函数pauseComp(毫秒)
function pauseComp(ms)
{
var curr = new Date().getTime();
ms += curr;
while (curr < ms) {
curr = new Date().getTime();
}
}
函数pauseComp(毫秒)
{
var curr=new Date().getTime();
ms+=电流;
而(电流<毫秒){
curr=新日期().getTime();
}
}
但是我想延迟的代码是使用raphaeljs绘制一些对象,显示一点也不平滑。我正在尝试使用doTimeout插件。我只需要延迟一次,因为延迟和要延迟的代码都在一个循环中。我没有身份证的要求,所以我没有使用它。
例如:
for(i; i<5; i++){ $.doTimeout(5000,function(){
alert('hi'); return false;}, true);}
for(i;iJavaScript是一种单线程语言。您不能将setTimeout
和同步处理结合起来。将会发生的事情是,计时器将失效,但JS引擎将等待处理结果,直到当前脚本完成
如果需要同步方法,只需直接调用该方法
如果您想在setTimeout之后处理某些内容,请将其包括在内或从timeout函数调用它。非超时循环(检查时间或计数为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);
(我只是快速拼凑了一下,所以尽管我相信它可以工作,但它可以在几个方面得到改进,例如,在“循环”中,它可以将索引值传递到回调函数中,以便您自己的代码知道它将进行哪一次迭代。但希望它能让您开始。)接受答案的变化与此答案一样好
此外,我同意优先选择setTimeout
和异步函数调用的警告,但有时,例如,在构建测试时,您只需要一个同步等待命令
function wait(ms) {
var start = Date.now(),
now = start;
while (now - start < ms) {
now = Date.now();
}
}
函数等待(毫秒){
var start=Date.now(),
现在=开始;
同时(现在-开始<毫秒){
now=Date.now();
}
}
如果您想在几秒钟内完成,请在while check上将start ms除以1000…我制作了一个简单的同步超时函数。它有两种不同的工作方式,回调和非回调
功能:
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");
下面是如何使用JQuerydoTimeout
插件
jQuery('selector').doTimeout( [ id, ] delay, callback [, arg ... ] );
从:“如果回调返回true,则在延迟后,doTimeout
循环将再次执行,创建轮询循环,直到回调返回非true值。”
var start=Date.now();
log(“开始:”,Date.now()-start);
var i=0;
$.doTimeout('myLoop',5000,function(){
log(i+1,Date.now()-start);
++一,;
返回i==5?假:真;
});
如果您想利用新的async/await语法,可以将set timeout转换为承诺,然后等待它
函数等待(毫秒){
返回新承诺((解决、拒绝)=>{
设置超时(()=>{
console.log(“完成等待”);
解析(毫秒)
},ms)
})
}
(异步函数Main(){
日志(“正在启动…”)
等待等待(5000);
log(“结束!”)
})();
使用函数生成器的解决方案。以表明它可以完成。不推荐使用
功能等待(毫秒){
常数根=函数*(){
const end=Date.now()+毫秒;
while(Date.now()
同步等待(仅用于测试!):
异步等待:
用法:
console.log('one')
syncWait(5000)
console.log('two')
(async () => {
console.log('one')
await asyncWait(5000)
console.log('two')
})()
delayedCall([
() => console.log('one'),
() => console.log('two'),
() => console.log('three'),
], 5000)
备选方案(异步):
用法:
console.log('one')
syncWait(5000)
console.log('two')
(async () => {
console.log('one')
await asyncWait(5000)
console.log('two')
})()
delayedCall([
() => console.log('one'),
() => console.log('two'),
() => console.log('three'),
], 5000)
节点解决方案
使用fs.existsSync()延迟
const fs=require('fs');
const uuidv4=require('uuid/v4');
/**
*将执行绑定到至少给定的毫秒数。这是无效的。
*@param毫秒最小等待毫秒数
*/
函数休眠同步(毫秒){
如果(毫秒使用新的Atomics API,您可以启动同步延迟而不会出现性能峰值:
const sleep=millides=>Atomics.wait(新的Int32Array(新的SharedArrayBuffer(4)),0,0,毫秒)
睡眠(5000)//睡眠5秒
log(“5秒后执行!”)
除了setTimeout是一个更好的选择,OP请求是一个同步方法。@ThinkBonobo回答correctly@robsonrosa-OP还说“我想延迟的代码是使用raphaeljs绘制一些对象,显示一点也不平滑”。您不能使用同步代码并绘制内容,因为在同步代码完成之前,屏幕不会重新绘制。仅仅因为OP要求某些内容是不可能的。用户正在专门寻找同步解决方案-setTimeout不是synchronous@Ryan-根据我之前的评论,只是因为他们要求som这是不可能的。同步延迟不能与他们正在进行的绘图共存,他们抱怨绘图不够平滑。请使用cb()
而不是eval(db)
。将脚本保存为字符串不是一个好的做法。用法:wait(5000,function(){console.log(“test!”)
。顺便说一句,如果需要回调,最好使用setTimeout。我想使用requestAnimationFrame(function(){})
可能比while
循环中的nothing
要好,在while循环中什么都不做会耗费大量cpu。请注意cpu的使用。当然,@JosephLust。它应该只用于测试而不是生产代码的另一个原因。这个生成器函数没有意义,它可以简单地内联。这也是同样的道理与其他ans中一样的粘连
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());
}