从闭包引出来的一系列问题
1. 不起眼的开始
for(var i = 0; i < 5; i++) {
setTimeout(function() { console.log(new Date, i)
}, 1000)
}console.log(new Date, i)很明显,由于异步的作用。到最后输出的结果为6个5
如果用箭头表示前后两次输出有1s的间隔,用,代表前后一起输出,那么输出结果是5->5,5,5,5,5
这个也很容易的就可以进行解释,先执行console.log(),再进行setTimeout()的异步操作。
追问1:如果变成 5 -> 0,1,2,3,4 该怎样处理?
首先可以使用闭包来解决这个问题:
for(var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() { console.log(new Date, j)
}, 1000)
})(i)
}console.log(new Date, i) // 5利用立即执行函数,来解决闭包造成的问题。
此外还可以使用setTimeout的第三个参数 文档:
for(var i = 0; i < 5; i++) {
setTimeout(function(j) { console.log(new Date, j)
}, 1000, i)
}console.log(new Date, i) // 5可能会有很多同学采用ES6的方式来避免:
for(let i = 0; i < 5; i++) {
setTimeout(function() { console.log(new Date, i)
}, 1000)
}console.log(new Date, i)但是此时并不能正确输出我们想要的结果,因为let声明的 i 产生了块级作用域,导致 for 循环外面的输出不能获取的 i ,所以此时会报错 i is not defined
追问2:如果把输出变为 0->1->2->3->4->5 呢?
其中一种比较容易想到的方法:
for(var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() { console.log(new Date, j)
}, 1000*j)
})(i)
}
setTimeout(function() { console.log(new Date, i)
}, 1000*i)但是js中定时器的触发时机是不确定的,每次循环都会产生一个异步操作之后,会有一个输出,那么完全可以使用Promise来解决这个问题。
const tasks = []for(var i = 0; i < 5; i++) {
(function(j){
tasks.push(new Promise((resolve) => {
setTimeout(() => { console.log(new Date, j)
resolve()
}, j*1000)
}))
})(i)
}Promise.all(tasks).then( () => {
setTimeout( () => { console.log(new Date, i)
}, 1000)
})将上面代码处理一下:
const tasks = []const output = function(i) { new Promise( (resolve) => {
setTimeout( () => { console.log(new Date, i)
resolve()
}, 1000*i)
})
}for(var i = 0;i < 5; i++) {
tasks.push(output(i))
}// 全部Promise执行完毕,执行最后一个输出iPromise.all(tasks).then( () => {
setTimeout( () => { console.log(new Date, i)
}, 1000)
})追问3:使用 async / await 怎么实现
// 模拟sleepconst sleep = (time) => new Promise((resolve) => {
setTimeout(resolve, time);
});(async () => { // 声明即执行的 async 函数表达式
for (var i = 0; i < 5; i++) { if (i > 0) { await sleep(1000);
} console.log(new Date, i);
} await sleep(1000); console.log(new Date, i);
})();
作者:宿雨jj
链接:https://www.jianshu.com/p/25d26fbc99ac
點擊查看更多內容
為 TA 點贊
評論
評論
共同學習,寫下你的評論
評論加載中...
作者其他優質文章
正在加載中
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦