async functions - Lee-hyuna/33-js-concepts-kr GitHub Wiki

Javascript의 Async/Await ν•¨μˆ˜ 탐ꡬ

원문: Exploring Async/Await Functions in JavaScript

ν”„λΌλ―ΈμŠ€λŠ” 비동기적 μ½”λ“œλ₯Ό 순차적으둜 μ‰½κ²Œ μ²˜λ¦¬ν•˜λŠ” 방법을 μ œκ³΅ν•œλ‹€. 우리의 λ‡Œκ°€ 비동기성을 효율적으둜 μ²˜λ¦¬ν•˜λ„λ‘ μ„€κ³„λ˜μ§€ μ•Šμ•˜λ‹€λŠ” 것을 κ³ λ €ν•˜λ©΄, 맀우 ν™˜μ˜λ°›μ„ λ§Œν•œ 좔가사항이닀. Async / await ν•¨μˆ˜λŠ” ES2017 ES8 ) 의 μƒˆλ‘œμš΄ μΆ”κ°€ κΈ°λŠ₯이닀. λ‚΄λΆ€μ μœΌλ‘  비동기 μž‘μ—…μ„ μˆ˜ν–‰ν•˜λ©΄μ„œ, ν‘œλ©΄μ μœΌλ‘  μ™„μ „νžˆ 동기식 μ½”λ“œλ₯Ό μž‘μ„±ν•  수 μžˆλ„λ‘ 도와쀀닀.

async ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 얻은 κΈ°λŠ₯은 ν”„λΌλ―ΈμŠ€μ™€ μ œλ„ˆλ ˆμ΄ν„°λ₯Ό κ²°ν•©ν•˜μ—¬λ„ κ΅¬ν˜„ν•  수 μžˆμ§€λ§Œ async ν•¨μˆ˜λŠ” μΆ”κ°€ μƒμš©κ΅¬ μ½”λ“œμ—†μ΄ ν•„μš”ν•œ 것을 μ œκ³΅ν•œλ‹€.

κ°„λ‹¨ν•œ 예제

μ•„λž˜ μ˜ˆμ œμ—μ„œλŠ”, λ¨Όμ € 2 초 후에 resolve둜 🀑 값을 λ„˜κΈ°λŠ” ν”„λΌλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λ₯Ό μ„ μ–Έν•œλ‹€. 그런 λ‹€μŒ async ν•¨μˆ˜λ₯Ό μ„ μ–Έν•œλ‹€. asyncν•¨μˆ˜λŠ” λ©”μ‹œμ§€λ₯Ό μ½˜μ†”μ— λ‘œκΉ…ν•˜κΈ° 전에 ν”„λΌλ―ΈμŠ€κ°€ reosolve λ˜κΈ°κΉŒμ§€ 기닀리기 μœ„ν•΄ await λ₯Ό μ‚¬μš©ν•œλ‹€.

function scaryClown() {
	return  new  Promise(resolve => {
		setTimeout(() => {
			resolve('🀑');
		}, 2000);
	});
} 
async  function msg() { 
	const msg = await scaryClown();
	console.log('Message:', msg); 
}
msg(); // Message: 🀑 <-- after 2 seconds

awaitλŠ” ν”„λΌλ―ΈμŠ€κ°€ resolveλ˜κ±°λ‚˜ reject 될 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦¬λŠ” 데 μ‚¬μš©λ˜λŠ” μƒˆλ‘œμš΄ μ—°μ‚°μžμ΄λ‹€. async ν•¨μˆ˜ λ‚΄μ—μ„œλ§Œ μ‚¬μš©ν•  수 μžˆλ‹€.

μ—¬λŸ¬ 단계가 κ΄€λ ¨λœ 경우 async ν•¨μˆ˜μ˜ 힘이 더 λΆ„λͺ…해진닀.

function who() {
	return  new  Promise(resolve => {
		setTimeout(() => {
			resolve('🀑');
		}, 200);
	});
}

function what() {
	return  new  Promise(resolve => {
		setTimeout(() => {
			resolve('lurks');
		}, 300);
	});
}

function where() {
	return  new  Promise(resolve => {
		setTimeout(() => {
			resolve('in the shadows');
		}, 500);
	});
}

async  function msg() {
	const a = await who();
	const b = await what();
	const c = await where(); 
	console.log(`${ a } ${ b } ${ c }`);
} 

msg(); // 🀑 lurks in the shadows <-- after 1 second

주의 ν•  점은, μœ„μ˜ μ˜ˆμ—μ„œ 각 λ‹¨κ³„λŠ” 순차적으둜 μˆ˜ν–‰λ˜λ©° 각 단계가 resolve, reject λ λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦°λ‹€. 단계λ₯Ό λ™μ‹œμ— μˆ˜ν–‰ν•˜λ €λ©΄ Promise.all 을 μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  ν”„λΌλ―ΈμŠ€κ°€ 이행 될 λ•ŒκΉŒμ§€ 기닀리면 λœλ‹€.

// ...

async  function msg() {
	// array destructuring
	const [a, b, c] = await Promise.all([who(), what(), where()]); 
	console.log(`${ a } ${ b } ${ c }`);
}

msg(); // 🀑 lurks in the shadows <-- after 500ms

Promise.all 은 전달 된 λͺ¨λ“  ν”„λΌλ―ΈμŠ€κ°€ resolve 되면 resolve 된 값이 μžˆλŠ” 배열을 λ°˜ν™˜ν•œλ‹€.

λ˜ν•œ μœ„μ˜ μ˜ˆμ œμ—μ„  μ½”λ“œλ₯Ό κ°„κ²°ν•˜κ²Œ λ§Œλ“€κΈ° μœ„ν•΄ array destructuring λ₯Ό μ‚¬μš©ν–ˆλ‹€.

ν”„λΌλ―ΈμŠ€ λ°˜ν™˜

Async ν•¨μˆ˜λŠ” 항상 ν”„λΌλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜κΈ°μ—, μ•„λž˜ μ½”λ“œλŠ” μ›ν•˜λŠ” κ²°κ³Όλ₯Ό 얻지 λͺ»ν•œλ‹€.

async function hello() {
	return  'Hello Alligator!';
}
const b = hello();
console.log(b); // [object Promise] { ... }

λ°˜ν™˜λ˜λŠ” 값은 ν”„λΌλ―ΈμŠ€μ΄κΈ° λ•Œλ¬Έμ—, λŒ€μ‹  λ‹€μŒκ³Ό 같이 ν•  수 μžˆλ‹€.

async function hello() {
	return  'Hello Alligator!';
}

const b = hello();

b.then(x =>  console.log(x)); // Hello Alligator!

λ‹¨μˆœνžˆ λ³€κ²½ν•˜λ©΄ μ•„λž˜μ™€ κ°™λ‹€.

async function hello() {
	return  'Hello Alligator!';
}

hello().then(x =>  console.log(x)); // Hello Alligator!

λ‹€λ₯Έ λͺ¨μ–‘

μ§€κΈˆκΉŒμ§€ 예제둜 async ν•¨μˆ˜λ₯Ό function μ„ μ–ΈμœΌλ‘œλ§Œ ν–ˆμ§€λ§Œ, ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œλ„ μ •μ˜ν•  수 μžˆλ‹€.

ν•¨μˆ˜ ν‘œν˜„μ‹μœΌλ‘œ λ§Œλ“  async

ν•¨μˆ˜ ν‘œν˜„μ‹μœΌλ‘œ μ •μ˜λœ 첫번째 예제λ₯Ό 보자.

const msg = async function() {
	const msg = await scaryClown();
	console.log('Message:', msg);
}

ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œ λ§Œλ“  async

μ—¬κΈ° λ˜‘κ°™μ€ μ˜ˆμ œκ°€ 또 λ‚˜μ˜€μ§€λ§Œ μ΄λ²ˆμ—” ν™”μ‚΄ν‘œ ν•¨μˆ˜λ‘œ μ •μ˜ν–ˆλ‹€.

const msg = async () => {
	const msg = await scaryClown();
	console.log('Message:', msg);
}

μ—λŸ¬ 처리

async ν•¨μˆ˜μ˜ 쒋은 점은 try ... catch 문을 μ‚¬μš©ν•˜μ—¬ 였λ₯˜ μ²˜λ¦¬κ°€ μ™„μ „νžˆ λ™κΈ°μ μœΌλ‘œ μˆ˜ν–‰λœλ‹€λŠ” 것이닀 . μ ˆλ°˜μ„ rejectν•˜λŠ” ν”„λΌλ―ΈμŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ μ•Œμ•„λ³΄μž.

function yayOrNay() {
	return new Promise((resolve, reject) => {
		const val = Math.round(Math.random() * 1); // 0 or 1, at random
		val ? resolve('Lucky!!') : reject('Nope 😠');
	});
} 
async function msg() {
	 try {
		 const msg = await yayOrNay();
		 console.log(msg);
	} catch(err) { 
		console.log(err);
	}
}
msg(); // Lucky!! 
msg(); // Lucky!! 
msg(); // Lucky!! 
msg(); // Nope 😠 
msg(); // Lucky!! 
msg(); // Nope 😠 
msg(); // Nope 😠 
msg(); // Nope 😠 
msg(); // Nope 😠 
msg(); // Lucky!!

async ν•¨μˆ˜κ°€ 항상 ν”„λΌλ―ΈμŠ€λ₯Ό λ°˜ν™˜ν•˜κΈ°μ— catchλ₯Ό μ‚¬μš©ν•˜μ—¬ μ²˜λ¦¬λ˜μ§€ μ•Šμ€ 였λ₯˜λ„ μ²˜λ¦¬ν•  수 μžˆλ‹€.

async function msg() {
	const msg = await yayOrNay();
	console.log(msg);
}

msg().catch(x =>  console.log(x));

이 였λ₯˜ μ²˜λ¦¬λŠ” ν”„λΌλ―ΈμŠ€κ°€ reject 될 λ•ŒλΏλ§Œ μ•„λ‹ˆλΌ μ‹€μ œ λŸ°νƒ€μž„ λ˜λŠ” ꡬ문 였λ₯˜κ°€ λ°œμƒν•˜λŠ” κ²½μš°μ—λ„ μž‘λ™ν•œλ‹€. μ•„λž˜ μ˜ˆμ œμ—μ„œ msg ν•¨μˆ˜λ₯Ό λ‘λ²ˆμ§Έ ν˜ΈμΆœν• λ•Œ ν”„λ‘œν† νƒ€μž… 체인의 toUpperCase λ©”μ„œλ“œκ°€ μ—†λŠ”number 값을 λ„˜κΈ΄λ‹€. try… catch 블둝은 κ·Έ μ—λŸ¬λ₯Ό μž‘μ•„ λ‚Έλ‹€ :

function caserUpper(val) {
	return new Promise((resolve, reject) => {
		resolve(val.toUpperCase());
	});
} 
async function msg(x) {
	try {
		const msg = await caserUpper(x);
		console.log(msg);
	} catch(err) {
		console.log('Ohh no:', err.message);
	}
} 
msg('Hello'); // HELLO
msg(34); // Ohh no: val.toUpperCase is not a function

ν”„λΌλ―ΈμŠ€ 기반 APIλ₯Ό ν†΅ν•œ Async ν•¨μˆ˜

Fetch API μž…λ¬Έμ„œμ—μ„œ λ³΄μ•˜ 듯이, ν”„λΌλ―ΈμŠ€ 기반의 μ›Ή APIλŠ” async ν•¨μˆ˜μ™€ 잘 μ–΄μšΈλ¦°λ‹€.

async function fetchUsers(endpoint) {
	const res = await fetch(endpoint);
	let data = await res.json();
	
	data = data.map(user => user.username);
	
	console.log(data);
} 

fetchUsers('https://jsonplaceholder.typicode.com/users'); // ["Bret", "Antonette", "Samantha", "Karianne", "Kamren", "Leopoldo_Corkery", "Elwyn.Skiles", "Maxime_Nienow", "Delphine", "Moriah.Stanton"]