所以,我正在创建一个机器人来在线玩视频游戏(完全合法,那里有一个用于机器人竞赛的服务器,不用担心)。代码是用JavaScript编写的,我现在只是采用它,而且我无法告诉机器人做某事,然后等待时间或条件,直到做其他事情。
到目前为止,我只是简单地将所有内容包装在巨大的setTimeout命令中,但这非常不优雅。
没有太多与发布相关的代码,但基本上我已经编写了很多代码,可以移动到特定位置,制动,追逐其他玩家,大多数使用递归setTimeout命令 - 按某些按钮,重置变量,然后如果条件不满足则再次启动该功能。如果我想移动到一个特定的位置然后在我完成时刹车,通常我会把代码放在这样:
moveTarget(target);
brake();
[...Execute rest of code...]
然而,JavaScript同时执行这两个命令,这显然不能很好地工作。有没有办法制作更像这样的东西(或等效的条件而不是指定的时间):
moveTarget(target);
wait3Seconds();
brake();
[...Execute rest of code...]
无需执行此操作:
moveTarget(target);
setTimeout(function(){
brake();
[...Execute rest of code...]
},3000);
鉴于我将会遇到多少这样的情况,我的代码最终会看起来像一个巨大的嵌套setTimeouts混乱,这不是很漂亮。有没有更好的办法?我已经在使用JQuery,所以我非常愿意在必要时使用它。
答案 0 :(得分:4)
没有更好的方法可以做到这一点。原因是任何类型的等待都将触发进入任务队列的任务。由于javascript是单线程的,因此它必须使用这些任务队列,因此如果存在指令,它将继续执行超过setTimeout的指令。
为了在延迟后执行代码,它必须在超时回调中,否则它将立即执行。
答案 1 :(得分:4)
JavaScript不会像您可能习惯的其他编程语言一样处理并发。相反,JavaScript只有一个主线程,而是有一个队列用于注册,然后按顺序处理事件。
由于这个原因,不要做很长时间阻塞线程的事情非常重要(比如Thread.sleep()这样的函数会这样做)。这就是为什么你应该使用setTimeout或setInterval来做这样的事情。
您始终可以创建自定义睡眠功能,以便以您请求的样式编写代码。这可能是这样的:
function sleep(millis) {
var startTime = Date.now();
while (Date.now() < startTime + millis) {}
}
但这将是非常,非常糟糕。这会在此睡眠功能运行时冻结页面。
你基本上需要重构你的代码,以便更多&#34; eventful&#34;。您应该编写JavaScript代码以使用回调和超时,而不是在同一个块中包含大的线性代码块。
因此,您展示的最后一个代码块实际上是您应该使用JavaScript的范例:
moveTarget(target);
setTimeout(function(){
brake();
[...Execute rest of code...]
},3000);
然而,你当然可以清理很多东西,如果不是[...Execute rest of code...]
,你将它拆分成其他函数并从你的setTimeout回调中调用它们。当然,在任何编程语言中保持代码块小而简洁是一个很好的经验法则。
您可能还有兴趣查看request animation frame function。
答案 2 :(得分:1)
如果您在具有wait命令的链中创建了所有方法,则可以执行此操作,类似于jQuery队列系统。
$("<div>").queue(function(next){
// do a
a();
next();
}).delay(3*1000).queue(function(next){
// after 3 seconds do b
b();
next();
}).delay(3*1000).queue(function(next){
// after 3 more seconds do c
c();
next();
}).dequeue(); //.dequeue() starts it, only has to be called to make a queue that isn't currently running begin.
所以你所要做的就是保持相同的链并继续添加它。