for循环中不修改timeout值, 每隔1秒输出

很简单的一个需求, 循环10次, 每隔1秒输出i的值, 伪代码如下

for(let i=0; i<10; i++) {
    setTimeout(function(){
        console.log(i)
    }, 1000)
}

地球人都知道这样会都输出一个值

用闭包可以实现1秒后输出所有值, 但是我想要的是每隔1秒输出一个值(不用改变timeout的时间, 比如:(i+1)*1000, 这种方式)

请问:这个如何实现?

补充一个@李引证的答案, 估计好多同学看的不太懂

  • 这段代码在node里面是运行不通的, 因为需要es7, 可以在浏览器里面运行

  • const sleep = time=>new Promise(resolve=>setTimeout(resolve,time));这段代码简写的很严重, 我改成详版

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

这样看的能清楚些

  • 其实这些sleep函数真的没干么事, 方法如其名, 只是sleep了一段时间

  • 其实await是有返回值的, 返回的是resolve的参数, 不信你试试这段代码

async function test() {
    for (let i = 0; i < 10; i++) {
        let t = await sleep(1000)
        console.log(t, i)
    }
}
阅读 7.6k
6 个回答

新的async/await语法可以轻松实现。

const sleep = time=>new Promise(resolve=>setTimeout(resolve,time));
(async function(){
   for(let i=0;i<10;i++){
       await sleep(1000);
       console.log(i);
   }
})()

如果要只想用ES6的话,也可以的,用生成器yield代替,并且写个自动run的辅助函数。

const next = (gen,val) => {
     const n = gen.next(val);
     !n.done && Promise.resolve(n.value).then(d=>next(gen,d));
 }
const run = genfunc => next(genfunc());
const sleep = time=>new Promise(resolve=>setTimeout(resolve,time));
run(function* (){
    for(let i=0;i<10;i++){
       yield sleep(1000);
       console.log(i);
    } 
})

如果是ES5的话,只能创造一个数组,然后在异步函数里不停的调用next来传递顺序,常用node的人应该对express的next不陌生吧。

function run(arr,func){
   var len = arr.length;
   function next(){
      if(!len) return;
      func(arr[arr.length-len],next);
      len--;
   }
   next();
}
var arr = Array.apply(null, {length: 10}).map(Function.call, Number);
run(arr,function(i,next){
   setTimeout(function(){
       console.log(i);
       next();
   },1000);
});

for(let i=0; i<10; i++) {

setTimeout(function(){
    console.log(i)
}, i*1000)

}

for(let i=0; i<10; i++) {
    (function(j) {
        setTimeout(function(){
            console.log(j);
        }, j*1000)
    })(i);
}

这样可以?

用setInterval

嵌套执行setTimeout即可

var arr = Array.from({length: 10}).map((ele, index) => index)
var nexttimeout = () => setTimeout(() => { console.log(arr.pop()); arr.length && nexttimeout()}, 1000)
nexttimeout()
let i = 0;

function foo (num) {
  setTimeout(function(){
        console.log(num);
        if (num < 10) { 
          foo(num + 1);
        }
    }, 1000)
}

foo(0);

案例

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题