[typescript] Promise와 Async/Await 구문

2021. 3. 11. 17:19typescript/typescript-grammar

동기와 비동기 API

동기란?

특정한 작업이 종료된 후 다음 줄의 작업을 실행하는 것을 의미하고 

 

비동기란? 

특정한 작업이 종료되기 까지 기다리는 것이 아니라 기다리지 않고 실행되는 것이다. 

 

js에서는 대부분의 작업들이 특별한 처리를 해주지 않으면 자동적으로 비동기적으로 실행되는 부분들이 많다. 

그렇기 때문에 라이브러리 사이에서는 비동기 방식과 동기 방식 모두 지원하는 것이 생기고 있다. 

 

예를 들어 

// 동기식
import {readFileSync, readFile} from 'fs';

console.log('read package.json using ...');
const buffer : Buffer = readFileSync('./package.json');
console.log(buffer.toString());

// 비동기식

readFile('./package.json', (error: Error, buffer: Buffer) =>{
	console.log('read package.json using asynchronous api...);
    console.log(buffer.toString());
});

 

위의 코드와 같이 위가 동기식, 아래가 비동기식이다.

 

동기 코드의 경우에는 readFileSync가 종료될 시에 buffer에 데이터를 저장하고 로그로 출력시킨다. 

 

아래 파일에 파일 이름을 넣어둔 후 콜백함수를 사용해서 결과값을 buffer로 받아온다.  

 

그리고 이런 것을 편하게 사용하기 위해 js에서는 Promise와 Async/Await을 제공하고 있다. 

 

// promise 방식
const readFilePromise = (filename:string): Promise<string> =>
	new Promise<string>((resolve, reject)=>{
		readFile(filename, (error: Error, buffer: Buffer)=>{
			if(error)
				reject(error)
			else
				resolve(buffer.toString())
	})
})

// async 방식
(async () =>{
	const content = await readFilePromise('./package.json')
	console.log('read package.json using Promise and async/await...')
})()

 

js는 단일 스레드이기 때문에 과도한 동기적 프로그래밍을 사용하면 좋지 못합니다. 왜냐하면 위를 예를 들어서 하나의 동기식 코드를 만나게되면 하나의 파일을 읽을 때까지 os는 기다리게 됩니다. 그리고 파일을 읽을 때까지 기다린 뒤 반환값을 받아야 다시 코드가 진행됩니다. 이럴 경우 웹 서버의 경우 동기값을 반환할 때까지 잠시 멈추게 되는 것입니다. 

 

Promise 이해하기

우선 Pormise를 사용하기 위해서는 new Promise를 통해 객체를 만들어주어야 합니다. 그리고 Promise의 콜백 함수에는 (resolve, reject)를 등록해야합니다. 

const numPromise: Promise<number> = new Promise<number> (콜백함수)
const strPromise: Promise<string> = new Promise<string> (콜백함수)
const arrayPromise: Promise<number[]> = new Promise<number[]>(콜백함수)

new Promise<T>((
	resolve: (sucessValue: T) => void, 
    reject: (any) => void) => {
    })
    
 

 

Promise.resolve 메서드 

 

이전에 콜백함수에 resolve라는 값이 있었는데 이는 Promise.resolve와 같은 클래스 메소드입니다. resolve안에 값을 넣어주면 연결된 then에 값이 전송됩니다. 

Promise.resolve(1).then(value => console.log(value)) // 1

Promise.resolve('hoony').then(value=>console.log(value)) // hello

Promise.resolve([4, 5, 6]).then(value=>console.log(value)) // [4 5 6]

Promise.resolve({name: 'hoony', age: 25}).then(value=>console.log(value)) // {name : 'Jack', age:32}

 

Promise.reject 메서드

 

reject에는 Promise가 실패했을 때(오류 등)의 사용하는 도구이고 reject의 파라미터로는 error 객체가 들어가게된다. 

Promise.reject(new Error('error')).catch((err:Error) => console.log('error: ', err.message))

 

then 체인

 

then을 통해 반환한 값은 또다른 then을 통해서 수신할 수 있습니다. 중간에 에러가 발생하면 .catch를 사용하여 에러또한 수신할 수 있습니다. 

Promise.resolve(1).then(value => return value).
then((value: number) =>{
	console.log(value)
    return [1,2,3]
})
.then((value:number[])=>{
	console.log(value)
    return {name: 'jack', age:32};
})
.then((value: {name:string, age: number})=>{
	console.log(value)
})

 

Promise.all 메서드

all(프로미스 객체 배열: Promise[]): Promise<해소된 값들의 배열(혹은 any)>

all은 Promise를 객체로 파라미터를 받은 다음 실행된 후 반환되는 값들을 배열형태로 반환합니다. 

 

const getAllResolveResult = <T>(promise: Promise<T>[]) => Promise.all(promises)

getAllResolveResult<any>([Promise.resolve(true), Promise.resolve('hoony')])
.then(result => console.log(result)) //[true, 'hoony']

getAllResolveResult<any>([Promise.reject(new Error('에러 발생')), Promise.resolve('hello')])
.then(result => console.log(result))
.catch(error => console.log('error:', error.message))

 위 코드를 보면 주의 해야 할 점이 all에서 한개라도 에러가 발생하게 되면 then이아니라 catch가 실행되게 된다. 

 

 

Async/Await

await의 경우 피연산자의 값을 반환해 줍니다. 만일 피연산자가 Promise 객체이면 then 메서드를 호출해 얻은 값을 반환해줍니다. 

let value = await Promise 객체 혹은 값

 

async 

 

위의 await구문은 항상 async라는 이름의 함수 수정자가 있는 함수 몸통에서만 사용할 수 있습니다. 

const hiasync = async()=>{
	await Promise 객체 혹은 값
}

 

async 함수의 성질

 

- 일반함수 처럼 사용가능

- promise 객체로도 사용할 수 있다. -> 이때문에 Promise.all에도 적용해서 사용할 수 있다. 

 

async 함수는 값을 반환할 수 있습니다. 이때 반환값은 Promise 형태로 변환되므로 then 메소드를 통해서 반환되는 값을 얻어야 합니다. 

 

const hi = async ()=>{
    return [1, 2, 3];
}

const asyncReturn = async ()=>{
    const result = await hi()
    console.log('value0:', result)
    return result;
}

asyncReturn().then(value => 
    console.log('value1: ', value))

제일 외부에서는 then을 통해서 값에 접근해야합니다. 

 

결과 

value0: [ 1, 2, 3 ]
value1:  [ 1, 2, 3 ]

'typescript > typescript-grammar' 카테고리의 다른 글

typescript - this and arrow functions  (0) 2020.03.06
6. typescript - class  (0) 2020.03.06
5. typescript - interfaces  (0) 2020.03.03
4. typescript - 변수 선언  (0) 2020.02.29
3. typescript - 타입  (0) 2020.02.27