forEach中使用async await的問題


先看一道有意思的題目:想一下執行的過程和結果

const list = [1, 2, 3]
const square = num => {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve(num * num)
		}, 1000)
	})
}

function test() {
	list.forEach(async x => {
		const res = await square(x)
		console.log(res)
	})
}

test()

以上代碼執行情況是:在一秒后直接輸出1、4、9

你可能期望的是一次循環走完后,再走下一次循環,然而現實卻並不是這樣。因為forEach只會將異步的代碼執行了,但是並不會等待回調的結果,所以加了await也是無效的。

forEach在執行異步的時候類似並發執行,假設你在這遍歷十次,就好像十次同時都去執行了一樣,但是JavaScript是單線程的它不存在同時執行的概念。

  • 這里需要先區分一下並發和並行的概念。

    • 並發(concurrency):例如Node.js早期就是以高並發的能力而聞名的,雖然現在GO語言等適合做高並發,
    • 並行(parallelism):同時執行的概念是並行里才存在的,而並發並不存在同時執行的概念,只有支持多線程和多進程的語言才可以執行並行。
  • Python 也是單線程的,雖然存在偽線程通過new Thread()實現

  • Java和C#中是有多線程的,多線程需要涉及線程同步的概念,這里就需要鎖 lock 的機制。

  • JavaScript是單線程機制,但是為何可以實現並發的操作。(宏任務、微任務)

  • 單線程的機制實質還是因為現在CPU運算速度足夠快,在代碼快速運行時看起來像是同時運行的樣子,然而並不是同時執行的。

  • CPU密集型操作:JavaScript不適合做CPU密集型的操作,因為會使CPU負載過高,導致代碼執行阻塞。

  • 資源密集型操作:例如網絡請求、查詢數據庫、讀寫文件。

舉例假設查詢數據庫需要3秒,這個時候JavaScript不會等待,因為這3秒是數據庫的運算能力需要消耗的時間,跟JavaScript沒有關系,所以這個時候JavaScript可以利用這3秒鍾的時間去執行別的代碼片段(這里就涉及到JavaScript中的Eventloop事件機制),這樣看起來就行是同時執行的一樣,實現了並發的操作,而不是同時執行代碼片段,這是並行的概念。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM