循环中 Promise 的 javascript 睡眠功能
Posted
技术标签:
【中文标题】循环中 Promise 的 javascript 睡眠功能【英文标题】:javascript sleep function by Promise in loop 【发布时间】: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]);
)
但它没有用,有人可以帮助我吗?谢谢~
【问题讨论】:
见:***.com/q/750486/5647260 【参考方案1】:Sleep
函数正在执行异步,for
循环在执行任何sleep
调用之前完成。
因此,for
循环的最后一个值将是3
,而window.open
函数将接收未定义的value
的value
作为参数。
看看:
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 来实现此目的。
【讨论】:
以上是关于循环中 Promise 的 javascript 睡眠功能的主要内容,如果未能解决你的问题,请参考以下文章
Javascript等待Promise在返回响应之前完成for循环
js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)