2

I intend to open a series of urls in firefox,each one should be opened after another in 10 minutes, here is my code should be execute in firebug console:

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]); 
})

But it didn't work, could anyone help me ? Thank you~

Wang
  • 31
  • 1
  • 3

5 Answers5

7

Sleep function is executing asynchronously and the for loop finished before executing any of the sleep calls.

So, the last value of for loop will be 3, and window.open function will receive as parameter the value of urls[3] which is undefined.

Have a look:

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); 
})

One solution is to use let keyword.

You should use let keyword in order to use enclosed value of i variable.

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.

Mihai Alexandru-Ionut
  • 47,092
  • 13
  • 101
  • 128
4

Promises work very well with async/await functions.

The following will declare a new asynchronous function (i.e. it will execute outside after the function is called). The code of the async function reads very easily because it reads like a synchronous function:

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

(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)
    }
})()
    

Here's a version using Promise chaining:

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

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();
    } );
}
Stephen Quan
  • 21,481
  • 4
  • 88
  • 75
0

The problem is i will =3 on in all 3 cases, so you need to save i for example

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]); 
})

But even this will not help, because first new tab will opened, your code in inactive tab will be stopped by browser.

qiAlex
  • 4,290
  • 2
  • 19
  • 35
0

Think a interval + entries would be better suited for this, here is an example with 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)
Endless
  • 34,080
  • 13
  • 108
  • 131
-1

You could use setInterval() or setTimeout() instead of sleep to achieve this.