天天看點

異步處理的終極方案:async,await

進入個人部落格 Eighteen Blog

異步函數我們經常會用到,最為常見的就是ajax,利用ajax請求我們的服務端擷取資料,然後執行回調函數。

一,普通的ajax

ajax(url,(res)=>{
	console.log(res);
	})
           

最普通的異步請求函數,那麼當我們有兩個異步請求,且請求B需要依賴請求A的時候,該怎麼處理?

//ajaxA
ajax(url1, (resA) => {

	ajax(url2, (resB) => {
		
		console.log(resA);
		console.log(resB);
		// ajax(url3, ()=>{} ...  類似這樣有多少個依賴關系就一直嵌套,形成回調地獄(函數多層嵌套)。
	
	})

})
           

這樣處理我們的多層異步依賴,會最終形成金字塔的形狀,層層嵌套,看不清代碼邏輯,難以維護且難以追蹤。

二,使用promise處理異步回調,使其變成鍊式調用。

new Promise((resolve, reject) => {

	  ajax(url, (res)=>{
	 		resolve(res)//完成狀态   promise的狀态隻可定義一次,下一行的reject将不起作用。
	 		reject('reject')//拒絕狀态
		})

})

.then(res => {

		return new Promise((resolve, reject) => {
	  	//如果第二個為異步函數,繼續return 一個promise,resolve的參數即是下個回調的參數。
		
			ajax(url, (res) => {
		 		resolve(res);
			})
			
		})
		
})

.then(res => {
	return '非異步';//return 的值是下一個then中的參數。
})

.then(res => {
	console.log(res); // "非異步"
})
           

至此,我們的代碼看起來清晰了不少,當然我們可以遵守盡量給函數語義命名的規則,進一步的簡化代碼。

// 變量聲明函數

let promise1 = new Promise((resolve, reject) => {

 	ajax(url, (res)=>{
 		resolve(res)//完成狀态   promise的狀态隻可定義一次,下一行的reject将不起作用。
 		reject('reject')//拒絕狀态
	})

})

let promise2 = new Promise((resolve, reject) => {  
	//如果第二個依然為異步函數,繼續return 一個new promise,resolve的參數即是下個回調的參數。
	
	ajax(url, (res)=>{
 		resolve(res)
	})
	
})

promise1()

.then(promise2)

.then(res => {
	return '非異步';//return 的值是下一個then中的參數。
})

.then(res => {
	console.log(res); // "非異步"
})
           

這樣代碼更加的簡介清晰。

三,我們可以使用async和await解決回調問題。

function takeLongTime() {
    
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(10), 1000);
    });
    
}

function takeLongTime2(v) {
    
    console.log(v); // 10
    
    return new Promise(resolve => {
        setTimeout(() => resolve(v + 20), 10);
    });

}

async function test() {
    const v = await takeLongTime(); //10
    const b = await takeLongTime2(v);  //30
    console.log(b);
}

test();
           

await 我們從名字可以看出來意思是等待異步的意思,即它可以讓異步回調變得像同步函數,并且會阻塞下一步,但是!這一切都是發生在async中的,而async是異步的,是以整個js并不會被阻塞。是以await要寫在async中。當然單純的await和async是并不能解決問題。可以看到還是需要promise的。

async和await内部實作了Generator ,然後結合promise,是他們的文法糖,大家可以自行了解一下。(它可以使函數内部分步執行)

繼續閱讀