1. 程式人生 > 其它 >Promise、async/await實現非同步操作

Promise、async/await實現非同步操作

併發與並行

  • 併發:對於單核處理器,同一時間內多個程式同時進行,這些程式在微觀上是交替進行的
  • 並行:對於多核處理器,同一時刻內有多個程式同時進行

同步與非同步

  • 同步 Synchronous :前一個任務執行完畢後,後一個任務才能進行。
  • 非同步 Asynchronous:多個任務可同時進行——多執行緒程式設計

JavaScript沒有多執行緒概念,而是通過函式回撥實現單執行緒“併發”。比如通過fetch獲取網路資源,獲取過程先會被跳過,去執行其他任務,等資源獲取完畢後再執行回撥函式。即在同一個執行緒中,要等待的任務先不需等待的任務執行,直到等待完獲取到資源後,再插隊進來。

setTimeout()實現非同步

setTimeout(()=>{
	console.log('三秒後執行')
},3000)

//面臨“回撥地域” CallBack Hell 問題
setTimeout(()=>{
	console.log('三秒後執行')
	setTimeout(()=>{
		console.log('三秒後執行')
		setTimeout(()=>{
			console.log('三秒後執行')
		},3000)
	},3000)
},3000)

Promise實現非同步

能夠通過鏈式結構將多個非同步操作串聯起來,而不需要多層巢狀

  • 方法:then、catch、all、finally
const goal=70
const result = new Promise((resolve,reject)=>{
 if (goal>=60){
	 resolve('良好')
 }else{
	 reject('不及格')
 }
})

  
result.then(e=>{
	console.log('你通過了考試!')
}).catch(e=>{
	console.log('非常遺憾,你未能通過考試!')
}).finally(()=>{
	console.log('感謝你參與本次測試!')
})

async/await與promise

  • async表明了某函式的返回值是非同步物件(如promise物件)

    async function f(){/*返回非同步物件promise*/}
    
    //such as
    async function f(){
    	return new Promise((resolve,reject)=>{/*...*/})
    }
    
  • await常跟著一個promise物件,等待非同步執行

    async function getResult(){
    	const response=await fetch('...') //fetch返回的是非同步物件
    	text=response.json()
    	console.log(text)
    }
    

多個非同步操作

  • forEach會立刻執行,下面寫法會直接跳到console.log,所以forEach無法實現非同步。
    async function f(){
    	[1,2,3].forEach(async i =>{
    		await someAsyncOperations()
    	})
    	console.log('完成啦')
    }
    
  • 可以用for迴圈實現非同步
    async function f(){
    	for(let i of [1,2,3]){
    		await someAsyncOperations()
    	}
    	console.log('完成啦')
    }
    
  • 升級版,for await非同步併發。
    async function f(){
    	const promises=[
    		someAsyncOperations(),
    		someAsyncOperations(),
    		someAsyncOperations()
    	]
    
    	for await (let result of promises){
    		//
    	}
    	console.log('完成啦')
    }
    

Await和Async

  • async函式內如果碰到await,會等待非同步完成後再執行下一個函式
    async function getStockPriceByName(name) { 
    	let symbol = await getStockSymbol(name);
    	let stockPrice = await getStockPrice(symbol); 
    	return stockPrice; //返回promise物件
    }
    getStockPriceByName('goog').then(()=>{/*...*/})
    
  • async函式的return會成為then回撥的引數
    async function f() { return 'hello world'} 
    f().then(v => console.log(v))
    
  • await後面的結果如果是reject,會終止程式。如果想繼續,用try catch
    async function f() { 
    	try { 
    		await Promise.reject('出錯了'); 
    	} catch(e) {
    		console.log('出錯了')
    	} 
    	return await Promise.resolve('hello world'); 
    } 
    
    f() .then(v => console.log(v))