問題
在forEach使用 async 和 await時凳兵,期望結(jié)果和實際結(jié)果不一致
期望結(jié)果: 隔一秒打印1次 1, 2, 3, 4 總時長 4s
實際結(jié)果: 一秒之后 1, 2, 3, 4全被打印 總時長 1s
let array = [1, 2, 3, 4]
const fun1 = (val) => {
return new Promise((reslove, reject) => {
setTimeout(() => {
reslove('1')
console.log(val)
}, 1000)
})
}
array.forEach(async function (item) {
await fun1(item)
})
原因分析
參考資料
MDN描述:forEach() 期望的是一個同步函數(shù)友瘤,它不會等待 Promise 兌現(xiàn)拆撼。在使用 Promise(或異步函數(shù))作為 forEach 回調(diào)時储矩,請確保你意識到這一點可能帶來的影響剿牺。
// 自己實現(xiàn)一個myForEach方法
Array.prototype.myForEach = function(callBack, thisArg) {
for(let i = 0; i < this.length; i++) {
callBack.call(thisArg, this[i], i, this)
}
}
從上面代碼可以看出裳擎,myForEach內(nèi)部執(zhí)行callBack時,沒有await關(guān)鍵字斯碌。
解決:
方案1.使用 for循環(huán)代替forEach
let array = [1, 2, 3, 4]
const fun1 = (val) => {
return new Promise((reslove, reject) => {
setTimeout(() => {
reslove('1')
console.log(val)
}, 1000)
})
}
const fun2 = async () => {
for (let i = 0; i < array.length; i++) {
await fun1(array[i])
}
}
fun2()
項目中例子記錄
-
需求:讓DOM元素逐個出現(xiàn)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.divStyle {
display: inline-block;
margin: 10px;
width: 100px;
height: 100px;
scale: 0;
transition: all .5s ease-in-out;
background: grey;
border: 5px;
}
</style>
</head>
<body>
<script>
function createDiv() {
const divEl = document.createElement('div')
divEl.classList.add('divStyle')
setTimeout(() => {
divEl.style.scale = 1
}, 50)
document.body.appendChild(divEl)
}
const addDivFun = async () => {
for (let i = 0; i < 10; i++) {
const fun = () => {
return new Promise((reslove) => {
setTimeout(() => {
createDiv()
reslove()
}, 1000)
})
}
await fun()
}
}
addDivFun()
</script>
</body>
</html>