Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/417.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 具有动态持续时间的setTimeout函数_Javascript - Fatal编程技术网

Javascript 具有动态持续时间的setTimeout函数

Javascript 具有动态持续时间的setTimeout函数,javascript,Javascript,我有一个setTimeout函数,可以迭代值: var content=['1','2','3','4','5'] 风险值持续时间=['10000','10000','20000','10000','30000'] 对于(i=0;i

我有一个setTimeout函数,可以迭代值:

var content=['1','2','3','4','5']
风险值持续时间=['10000','10000','20000','10000','30000']
对于(i=0;i}
代码的问题是for循环在不等待setTimeout完成的情况下进行迭代。
我建议像这样使用一点递归

var content=['1','2','3','4','5'];
风险值持续时间=['10000'、'10000'、'20000'、'10000'、'30000'];
var i=0;
var循环=函数(){
setTimeout(函数(){
if(++i}
正如另一张海报所提到的,您可能希望每个超时从最后一个超时的末尾开始。您可以使用建议的“递归”方法,但承诺将产生更可读的代码。首先,我们将编写一个
wait
例程,该例程返回一个承诺,该承诺在若干毫秒内解析:

function wait(n) {
    return new Promise(function(resolve) { setTimeout( resolve, n); });
}
现在,我们可以按如下方式重写您的循环:

var promise = Promise.resolve();

for (i = 0; i < content.length; i++) {
    promise = promise . then(function() { return wait(duration[i]; });
}
如果你不知道如何减少,这是很值得学习的

但是想象一下,如果跳过所有这些,简单地做一些事情,而不是设置超时,就在那里等待,那该有多好。事实证明,使用
async
函数实际上可以做到这一点:

async function wait_series(duration) {
^^^^^
    for (i = 0; i < content.length; i++) {
        await wait(duration[i]);
        ^^^^^
    }
}
使用异步函数或其基于
co
的等效函数的优点是,您可以像以前那样为循环编写常规的
。它们本质上允许您以同步思维编写异步代码。你不再需要考虑承诺(尽管
co
使用承诺在幕后发挥了神奇的作用)

你可能会说,写一系列连续的超时似乎需要学习很多东西。但实际上,承诺和异步函数最终比编写超时(调用函数然后设置其他超时)更容易

递归解 如果您喜欢递归解决方案,这里有一个稍微简化的版本,它实际上也可以工作(通过在最后通过
()
第一次调用
循环
):


“然而,持续时间不是动态的。”你能详细说明一下吗?显然,您正在将不同的值传递给
setTimeout
(至少其中一些值是这样的)。我相对确信JS会自动将它们转换为数字,但是的,这些应该是数字。我将您的示例代码转换为可运行的代码段。在Chrome中,它对我来说很好(等待30秒,直到最后一个警报对话框出现)。不要将字符串传递给超时。“这不起作用”也许你只是对代码正在执行的操作有错误的期望。但由于你还没有解释你期望的行为,我们无法真正帮助你。如果代码不符合您的要求,您可能只是编写了错误的解决方案。虽然允许OP没有明确说明,并且给出了一个糟糕的标题,但拒绝做出明显的(?)假设似乎有点天真,即意图是超时应按顺序运行,或者至少发布一条评论,询问情况是否如此。我不明白为什么这个问题应该被关闭或否决;它包含了讨论异步性的好材料。如果SO的目标是帮助人们解决他们的问题,那么帮助他们澄清和构建他们的问题,包括建议他们可能缺少的内容,无疑是其中一个有价值的方面。为什么(在原始代码中)需要“等待setTimeout完成”?原始代码工作正常。但是谁第一次调用
loop
呢?@GregHewgill,因为这可能是OP的意图,这是一个完全合理的,而且很可能是正确的假设,尽管正确的协议可能是在回应之前在评论中澄清这一点。OP明确表示,原始代码并没有“很好地工作”,尽管他承认他没有很好地解释它不工作的确切方式或他想要什么。因此,在这种情况下,我们能帮助他澄清他的问题陈述,而不是投票让他被遗忘吗?@torazaburo:事实上,OP没有解释代码实际应该做什么。(为了记录在案,我没有投反对票,而是试图帮助改进这个问题。)谢谢你详细、周到的回答。我将在几分钟内尝试您的一个或多个解决方案,并让您知道其进展情况。另外,感谢您的时间和努力,并提供了有益的反馈。
async function wait_series(duration) {
^^^^^
    for (i = 0; i < content.length; i++) {
        await wait(duration[i]);
        ^^^^^
    }
}
function wait_series(duration) {
    co(function *() {
    ^^
        for (i = 0; i < content.length; i++) {
            yield wait(duration[i]);
            ^^^^^
        }
    });
}
function wait_series(duration) {
    var i = duration.length;
    (function loop() {
        if (i--) setTimeout(loop, duration[i]);
    })();
      ^^
}