为什么这个promise最后一个打印结果是5?

打印出0~4我能想明白,为什么会最后一行打印的是5呢?5是什么时候传入的

const tasks = []; // 这里存放异步操作的 Promise
const output = (i) => new Promise((resolve) => {
    setTimeout(() => {
        console.log(new Date, i);
        resolve();
    }, 1000 * i);
});

// 生成全部的异步操作
for (var i = 0; i < 5; i++) {
    tasks.push(output(i));
}

// 异步操作完成之后,输出最后的 i
Promise.all(tasks).then(() => {
    setTimeout(() => {
        console.log(new Date, i);
    }, 1000);
});
阅读 2.8k
4 个回答

你打印的是全局变量i 而这个变量在for循环执行完后就是5了

i是全局变量,for循环最后一次,i++,尽管跳出了循环,但i变成了5,promise.all().then()里面那个setTimeout里打印了i,所以最后就变成了5

for循环和Promise.all作用域在同一级 所以i是5

使用var声明的变量是没有局部作用域的概念,只有函数作用域。

    for (var i = 0; i < 5; i++) {
        tasks.push(output(i));
    }
    // 异步操作完成之后,输出最后的 i
    Promise.all(tasks).then(() => {
        setTimeout(() => {
            console.log(new Date, i);
        }, 1000);
    });

这种写法和下面的写法是一样的效果:

    var i = 0
    for (; i < 5; i++) {
        tasks.push(output(i));
    }
    // 异步操作完成之后,输出最后的 i
    Promise.all(tasks).then(() => {
        setTimeout(() => {
            console.log(new Date, i);
        }, 1000);
    });

因为i是在最外层作用域的,而then中的回调是在所有promise都resolve之后才执行的,这是 i 已经被赋值为5,所以输出5.
如果使用let声明i,你就会看到报错的情况

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