1. 程式人生 > >Javascript中使用 async/await 進行非同步程式設計

Javascript中使用 async/await 進行非同步程式設計

介紹

  • es2017標準中寫入了`async/await`用法
  • 能用同步的方式來寫非同步程式碼
  • 在使用async/await之前,需要了解Promise規範

基本用法

async/await 的基本使用方法非常的簡單,先來看一段程式碼程式碼

const promise = () => {
	reuturn new Promise((resolve, reject) => {
		setTimeout(() => {
			resolve('resolved')
		}, 3000)
	})
};
const foo = async () => {
	const result = await promise();
	console.log(result);
	// 'resolved'
}
foo();
首先使用 async關鍵詞來宣告一個非同步函式 fooasync關鍵詞在這裡有兩個作用:
  1. 使得在函式 foo 內可以使用 await關鍵詞來暫時阻塞函式內部程式碼的執行.
  2. 使得函式 foo 立即返回一個 Promise 物件.
其次在定義好的非同步函式 foo 中使用 await 關鍵詞來阻塞當前函式,直到它後面的 Promise 處理完成. await 的作用:
  1. 暫時阻塞當前非同步函式, 等待 Promise 處理完成後繼續向下執行函式.
  2. 如果Promise正常處理完成, await 會將resolve的結果作為返回值返回.
所以,該段程式碼最後的執行結果是在等待3秒後,輸出'resolved'.

注意事項

  • async 函式不管你是否使用 return 關鍵詞返回, 一旦呼叫會立刻返回一個pending狀態的 Promise 物件, 直到它執行完成(內部所有的 await 表示式執行完成), 才會呼叫resolve方法, 並將它的返回值作為引數傳遞出去.
    const foo = async () => {
    	const result = await promise();
    	console.log(result);
    	// 'resolved'
    	return result;
    }
    foo().then(value => {
    	console.log(value);
    	// 'resolved'
    });
  • 如果 async 函式並沒有返回值或者並沒有使用 return關鍵詞, 那麼在函式執行完後,將會呼叫 resolve(undefined).
    const foo = async () => {
    	const result = await promise();
    	console.log(result);
    	// 'resolved'
    	// return;
    }
    foo().then(value => {
    	console.log(value);
    	// undefined
    });
  • await 關鍵詞只能在 async 函式內使用, 否則會報錯.
  • 如果 await 後面跟的不是一個 Promise 物件, 則立刻返回其後所跟的表示式的結果.

錯誤處理

async 函式中進行錯誤處理的時候可以採用兩種形式.

  • 可以使用 .catch() 方法處理錯誤, 但是這種方式並不推薦使用,如果一個 async 函式內有多個 await 表示式, 這種方式就會非常麻煩.
const foo = async () => {
	const result1 = await promise1().catch(err => {
		console.log(err);
	});
	const result2 = await promise2().catch(err => {
		console.log(err);
	});
	const result3 = await promise3().catch(err => {
		console.log(err);
	});
	...
}
  • 推薦的錯誤處理方法, 使用 `try`, `catch` 進行錯誤處理.一旦promise狀態變為 rejected, catch 會立馬撲捉到錯誤, 並把 rejcet() 的引數作為 err 傳遞出來.
const foo = async () => {
	try {
		const result1 = await promise1()
		const result2 = await promise2()
		const result3 = await promise3()
		...
	} catch (err) {
		console.log(err);
	}
}

async 函式的封裝和呼叫

首先, async 函式的封裝和普通函式的封裝基本相同

const foo = async () => {
	let result = await promise();
	try {
		result = await promise();
	} catch (err) {
		throw err;
	}
	return result;
}

async 函式的呼叫有兩種形式:

  • 使用Promise的鏈式呼叫
foo().then(result => {
		// todo
	}).catch(err => {
		// handle err
	})
  • 繼續在async函式中, 使用await表示式呼叫
const baz = async () => {
	let result;
	try {
		result = await foo();
	} catch (err) {
		// handle err
	}
	...
}