【问题标题】:javascript sleep function by Promise in loop循环中 Promise 的 javascript 睡眠功能
【发布时间】:2018-01-19 14:08:36
【问题描述】:

我打算在firefox中打开一系列url,每个url应该在10分钟内一个接一个地打开,这是我的代码应该在firebug控制台中执行:

function sleep (time) {
    return new Promise((resolve) => setTimeout(resolve, time));
}
var urls = ["https://www.google.com/","https://www.bing.com/","https://www.reddit.com/"];
for(var i = 0; i < urls.length; i++)
    sleep(600000 * i).then(() => {
    window.open(urls[i]); 
})

但它没有用,有人可以帮助我吗?谢谢~

【问题讨论】:

标签: javascript loops sleep


【解决方案1】:

Sleep 函数正在执行异步for 循环在执行任何sleep 调用之前完成。

因此,for 循环的最后一个值将是3,而window.open 函数将接收未定义的valuevalue 作为参数。

看看:

function sleep (time) {
    return new Promise((resolve) => setTimeout(resolve, time));
}
var urls = ["https://www.google.com/","https://www.bing.com/","https://www.reddit.com/"];
for(var i = 0; i < urls.length; i++)
    sleep(600*i).then(() => {
    console.log(i); 
})

一种解决方案是使用let关键字。

您应该使用let 关键字才能使用i 变量的封闭值。

function sleep (time) {
    return new Promise((resolve) => setTimeout(resolve, time));
}
var urls = ["https://www.google.com/","https://www.bing.com/","https://www.reddit.com/"];
for(let i = 0; i < urls.length; i++)
    sleep(6000*i).then(() => {
    window.open(urls[i]); 
})

jsFiddle solution.

【讨论】:

  • 谢谢亚历克斯,它有效。我发现javascript更难。谢谢大哥~
  • @Wang,不客气。不要忘记接受答案以帮助其他人。
【解决方案2】:

Promises 与 async/await 函数配合得非常好。

以下将声明一个新的异步函数(即在函数被调用后将在外部执行)。异步函数的代码读起来很容易,因为它读起来像一个同步函数:

function sleep(time) {
    return new Promise((resolve) => setTimeout(resolve, time))
}

(async function() {
    const urls = ["https://www.google.com/","https://www.bing.com/","https://www.reddit.com/"]
    for (let url of urls) {
        await sleep(1000)
        console.log(url)
    }
})()
    

这是一个使用 Promise 链接的版本:

function sleep(time) {
    return new Promise((resolve) => setTimeout(resolve, time))
}

const urls = ["https://www.google.com/","https://www.bing.com/","https://www.reddit.com/"];
let p = Promise.resolve();
for (let url of urls) {
    p = p.then( function () {
        return sleep(1000);
    } );
    p = p.then( function () {
        console.log(url);
        return Promise.resolve();
    } );
}

【讨论】:

    【解决方案3】:

    问题是 i 在所有 3 种情况下都将 =3,因此您需要保存 i 例如

    function sleep (time, i) {
        return new Promise((resolve) => setTimeout(() => resolve(i), time));
    }
    var urls = ["https://www.google.com/","https://www.bing.com/","https://www.reddit.com/"];
    for(var i = 0; i < urls.length; i++)
        sleep(1 * i, i).then((index) => {
        console.log(urls[index]); 
    })
    

    但即使这样也无济于事,因为第一个新标签页将打开,您在非活动标签页中的代码将被浏览器停止。

    【讨论】:

      【解决方案4】:

      认为一个区间 + entries 会更适合这个,这里是一个 es6 的例子

      const urls = [
        'https://www.google.com/',
        'https://www.bing.com/',
        'https://www.reddit.com'
      ]
      
      const entries = urls.entries()
      
      const loop = setInterval(() => {
        const {value, done} = entries.next()
        done ? clearInterval(loop) : open(value)
      }, 600 * 10)
      

      【讨论】:

        【解决方案5】:

        您可以使用 setInterval() 或 setTimeout() 代替 sleep 来实现此目的。

        【讨论】:

          猜你喜欢
          • 2021-03-07
          • 1970-01-01
          • 2019-10-21
          • 2023-03-29
          • 1970-01-01
          • 2010-11-11
          • 2011-02-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多