題目
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(new Date, i)
}, 1000)
}
console.log(new Date, i)
輸出:5 (1s)5 5 5 5 5
如何變成: 5(1s)0(1s)1(1s)2(1s)3(1s)4
經典解法
閉包
for (var i = 0; i < 5; i++) {
((i) => setTimeout(function() {
console.log(new Date, i)
}, 1000))(i)
}
console.log(new Date, i)
ES6: let
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(new Date, i)
}, i * 1000)
}
let i = 5
console.log(new Date, i)
追問
如何變成: 0(1s)1(1s)2(1s)3(1s)4 (1s)5
新解法
ES6: Promise
const tasks = []
const getPromise = i =>
new Promise((resolve, reject) => {
setTimeout(() => {
console.log(new Date, i)
resolve(i)
}, i * 1000)
})
for (let i = 0; i < 5; i++) {
tasks.push(getPromise(i))
}
Promise.all(tasks).then(iArr => {
setTimeout(() => {
const i = [...iArr].pop() + 1
console.log(new Date, i)
}, 1000)
})
ES7: async/await
const sleep = time => new Promise(resolve => setTimeout(resolve, time)); // 這個分號不能省
(async () => {
for (var i = 0; i < 5; i++) {
console.log(new Date, i)
await sleep(1000)
}
console.log(new Date, i)
})()
注
1 句尾分號不能省略的情況:
- 下一行是 IFFE 的
- 下一行是數組字面量的
2 套路:new 一個爲決議的 Promise, 其構造函數內使用定時器,定時器內 reslove
3 取一個數組最末尾的元素
arr[arr.length - 1]
[...arr].pop()
arr.slice(-1)[0]