Wang
Wang

Reputation: 41

javascript sleep function by Promise in loop

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~

Upvotes: 3

Views: 8366

Answers (5)

Stephen Quan
Stephen Quan

Reputation: 25956

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

Upvotes: 6

Endless
Endless

Reputation: 37815

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)

Upvotes: 0

Mihai Alexandru-Ionut
Mihai Alexandru-Ionut

Reputation: 48367

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.

Upvotes: 7

qiAlex
qiAlex

Reputation: 4346

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.

Upvotes: 0

Wouter Vandevelde
Wouter Vandevelde

Reputation: 904

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

Upvotes: -1

Related Questions