javascript - 使用 setTimeout 询问用户是否要等待或退出,但回调永远不会触发
问题描述
更新
解决了,有点。问题在于 Javascript 的单线程特性以及我对其事件模型的误解。循环不会被超时中断。
因此,解决方案是,我不使用回调,而是在开始循环之前获取时间戳,然后每次通过循环进行比较。如果超过 X 秒,我会触发confirm
对话框:
let start = new Date();
...
while ( keepGoing && matchNotFound )
{
...
let end = new Date();
if ( end - start > 10000 )
{
keepGoing = confirm( "This run seems to be taking a while - keep going?" );
start = end;
}
}
可能不是最有效或最惯用的解决方案,但它适用于我的目的。
原来的
我试图通过 调用一个函数setTimeout
,但无论我使用什么时间间隔,回调都不会触发。我不知道问题是否在于我如何设置呼叫,或者我对如何使用它的理解完全错误。
我正处于自学 Javascript 的早期阶段,并且已经编写了 Dawkins 的 Weasel 程序的一个版本作为练习。根据参数的不同,算法可能需要很长时间才能运行,所以我的想法是使用 setTimeout 调用一个函数,询问用户是否要继续并给他们保释的选项,有点像这样:
var keepGoing = true; // flag to continue main loop
var timeoutId; // stores result of setTimeout
...
/**
* Asks the user if they want to continue. If they do, reschedule this function to
* execute again after 5 seconds.
*/
function alertFunc()
{
keepGoing = confirm( "This is taking a while - do you want to continue?" );
if ( keepGoing )
{
timeoutId = setTimeout( alertFunc, 5000 );
}
}
/**
* Simulation loop
*/
function doWeasel()
{
/** simulation setup */
timeoutId = setTimeout( alertFunc, 5000 );
/** Loop until we find a match or the user gets bored */
while ( keepGoing && matchNotFound )
{
/** do the thing */
}
clearTimeout( timeoutId );
/** some cleanup */
}
无论如何,这是基本的想法。该doWeasel
函数与 HTML 文档中表单中的按钮单击相关联:
<html>
<head>
<!-- header stuff -->
</head>
<body>
<!-- long-winded explanation -->
<div class="formarea">
<form class="inputForm">
<!-- form stuff -->
<input type="button" value="OK" onclick="doWeasel()"/>
<input type="reset"/>
</form>
</div>
<div id="outputarea">
<h2>Output from the thing</h2>
<script type="text/javascript" src="weasel.js"></script> <!-- source for doWeasel() -->
</div>
</body>
</html>
我遇到的问题是它alertFunc
似乎永远不会触发 - 我添加了控制台日志记录以在输入函数时写入一条消息,但它永远不会出现。我已经在 Chrome 中运行了调试器,并在回调中设置了一个断点,但它从未到达过。
setTimeout
显然,无论是调用本身还是我尝试使用它的方式,我都做错了,但根据我迄今为止阅读的文档,我看不出它可能是什么。我对如何使用它的概念是完全错误的吗?
我是一个老 C 和 C++ 程序员,只涉足 HTML 和 Web 脚本编写,所以我可能只是不明白在这里做事的正确方法。
编辑
为了解决一些评论,这是一个工作页面 - 当我单击OK
模拟运行并动态构建输出表时。只是输入参数的组合导致它运行时间过长(直到浏览器抛出“此页面无响应”或我只是关闭选项卡)。
我可以在 Chrome 的调试器中跟踪脚本的执行,它调用setTimeout
并分配一个值给timerId
,但回调从未真正执行。对于默认参数,模拟运行完成并在页面上构建一个包含结果的表格。
也许这不是解决问题的正确方法 - 也许我需要添加另一个按钮来调用不同的功能keepGoing
设置false
。
编辑2
我写了一个快速而肮脏的原型来测试超时功能,我想我知道我的问题是什么。如果我不在循环中间,回调按预期执行,但如果我有一个循环旋转它不会。所以,我需要做一些关于如何处理异步事件处理的阅读。
解决方案
如果您确定 while 循环没有阻止下一行运行,则可能脚本尚未加载,并且在您将onclick
属性分配给<input>
元素时尚未定义函数,请尝试设置defer标记到您的脚本元素,以确保在文档被解析后执行脚本。否则在外部调用该函数可以正常工作。
推荐阅读
- react-native - 尺寸未知的 React-Native svg
- linux - 如何在Shell脚本中绘制星形图案?
- javascript - 每次单击扩展的图标时,React chrome 扩展都会插入到 DOM 中,应该只插入一次
- django - Django Forms - 如何为 Many2Many 字段添加 + 号
- ssh - Ansible:无法通过 ssh 连接到主机
- javascript - 允许用户在android中以黄色突出显示webview文本
- javascript - JavaScript 中的 SUM IFS
- typescript - Typescript 无法预测数组中索引的变量的可能类型
- c# - Nuget 包在安装时会从其参考项目中复制静态文件
- sass - sass 监视整个项目并添加后缀