๐ค Chapter 7: Promise์ async/await ๊ตฌ๋ฌธ
๐ฆ ๋น๋๊ธฐ ์ฝ๋ฐฑ ํจ์โ
๐ ๋๊ธฐ์ ๋น๋๊ธฐ APIโ
- Node.js์์ ํ์ผ ์์คํ
๊ณผ ๊ด๋ จ๋ ๊ธฐ๋ฅ์ ๋ชจ์๋
fs
ํจํค์ง๋ฅผ ์ ๊ณตํ๋๋ฐ, ๋๊ธฐ ๋น๋๊ธฐ ๋ฒ์ ์ผ๋ก ๋๋์ด ์ ๊ณตํ๋ค. ์๋ฅผ ๋ค์ด, ๋๊ธฐ ๋ฒ์ ์ธreadFileSync
์ ๋น๋๊ธฐ ๋ฒ์ ์ธreadFile
๋ก ์ ๊ณตํ๋ค.
import { readFileSync, readFile } from "fs";
// ๋๊ธฐ ๋ฐฉ์์ผ๋ก ์ฝ๊ธฐ
const buffer: Buffer = readFileSync('./package.json');
console.log(buffer.toString());
// ๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก ์ฝ๊ธฐ
readFile('./package.json', (error: Error, buffer: Buffer) => {
console.log(buffer.toString());
});
// Promise์ async/await ๊ตฌ๋ฌธ์ ์ฌ์ฉํ ์
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 () => {
const content = await readFilePromise('./package.json');
console.log(content);
})();
- API ํจ์๋ ์ผ๋ฐ ํจ์์ ๋ฌ๋ฆฌ ํ๋๋์คํฌ์ ์ ์ฅ๋ ํ์ผ์ ์ฝ๋ ๋ฑ ์คํ์ ๋ฌผ๋ฆฌ์ ์ธ ์๊ฐ์ด ์์๋๋ค.
- ๋ฐ๋ผ์ ํ์ผ ๋ด์ฉ์ ๋ชจ๋ ์ฝ์ ๋๊น์ง ํ๋ก๊ทธ๋จ์ ๋์์ ์ ์ ๋ฉ์ถ๋ ๋๊ธฐ ๋ฐฉ์์ API์ ํ๋ก๊ทธ๋จ์ ๋์์ ๋ฉ์ถ์ง ์๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์ฝ๋ฐฑ ํจ์๋ก ์ป๊ฒ ํ๋ ๋น๋๊ธฐ ๋ฐฉ์์ API๋ฅผ ์ ๊ณตํ๋ค.
- ๋น๋๊ธฐ API์ ์ฝ๋ฐฑ ํจ์๋ฅผ ๋น๋๊ธฐ ์ฝ๋ฐฑ ํจ์๋ผ๊ณ ํ๋ค. ๋น๋๊ธฐ ์ฝ๋ฐฑ ํจ์๋ ์ผ๋ฐ ํจ์์ ๋ฌ๋ฆฌ API์ ๋ฌผ๋ฆฌ์ ์ธ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์์ ํ๋ ๋ชฉ์ ์ผ๋ก๋ง ์ฌ์ฉํ๋ค.
๐ ๋จ์ผ ์ค๋ ๋์ ๋น๋๊ธฐ APIโ
- ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋จ์ผ ์ค๋ ๋๋ก ๋์ํ๋ฏ๋ก ๋ ์ ์์ผ๋ฉด
readFileSync
์ ๊ฐ์ ๋๊ธฐ API๋ฅผ ์ฌ์ฉํ์ง ๋ง์์ผ ํ๋ค. - ๋๊ธฐ API๊ฐ ์คํ๋๋ฉด, ์ด์์ฒด์ ๋ ๋๊ธฐ API์ ์์ ๊ฒฐ๊ณผ๋ฅผ ํจ์์ ๋ฐํ๊ฐ์ผ๋ก ๋๋ ค์ค์ผ ํ๋ค. ์ด ๋๋ฌธ์ ์ด์์ฒด์ ๋ ๋๊ธฐ API๊ฐ ์คํ๋ ์ฝ๋๋ฅผ ์ผ์์ ์ผ๋ก ๋ฉ์ถ ๋ค์, ๋ ๋ค๋ฅธ ์ค๋ ๋์์ ์ค์ ์์ ์ ์คํํด ์ผค๊ณผ๋ฅผ ์ป์ผ๋ฉด ๊ทธ๋์์ผ ์ ์ ๋ฉ์ท๋ ๋๊ธฐ API๋ฅผ ์คํํ๋ฉด์ ๊ฒฐ๊ด๊ฐ์ ๋ฐํํ๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ ๋๊น์ง ์ผ์์ ์ผ๋ก ๋ฉ์ถ๋ ํ์์ด ๋ฐ์ํ๋ค.
๐ ์ฝ๋ฐฑ ์ง์ฅโ
- ๋น๋๊ธฐ API๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋ฐฑ ํจ์์์ ๋ ๋ค์ ๋ค๋ฅธ ๋น๋๊ธฐ API๋ฅผ ํธ์ถํ๋ ์ฝ๋๋ฅผ ๋ง๋ค ๋ ์ฝ๋๊ฐ ๋งค์ฐ ๋ณต์กํด์ง๋ค.
import { readFile } from "fs";
readFile('./package.json', (error: Error, buffer: Buffer) => {
if (error) {
throw error;
} else {
const content: string = buffer.toString();
console.log(content);
}
readFile('./tsconfig.json',(err: Error, buffer: Buffer) => {
if (error) {
throw error;
} else {
const content: string = buffer.toString();
console.log(content);
}
})
});
Promise
๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฐ ์ฝ๋ฐฑ ์ง์ฅ์ ๋น ์ง ์ฝ๋๋ฅผ ์ข ๋ ๋ค๋ฃจ๊ธฐ ์ฌ์ด ํํ์ ์ฝ๋๋ก ๋ง๋ค ์ ์๋ค.
๐ฆ Promise ์ดํดํ๊ธฐโ
- ํ์
์คํฌ๋ฆฝํธ์์
Promise
๋ ๋ค์๊ณผ ๊ฐ์ด ์ ๋ค๋ฆญ ํด๋์ค ํํ๋ก ์ฌ์ฉ๋๋ค.
const numPromise: Promise<number> = new Promise<number>(์ฝ๋ฐฑํจ์);
const strPromise: Promise<string> = new Promise<string>(์ฝ๋ฐฑํจ์);
const arrayPromise: Promise<number[]> = new Promise<number[]>(์ฝ๋ฒกํ์);
- ํ์
์คํฌ๋ฆฝํธ
Promise
์ ์ฝ๋ฐฑ ํจ์๋ ๋ค์์ฒ๋ผresolve
์reject
ํจ์๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๋ ํํ์ด๋ค.
new Promise<T>((
resolve: (successValue: T) => void,
reject: (any) => void,
) => {
// ์ฝ๋ ๊ตฌํ
});
๐ resolve์ reject ํจ์โ
- ๋ค์์ ๋น๋๊ธฐ API์ธ
readFile
์ ํธ์ถํ๋ ๋ด์ฉ์ ํ๋ก๋ฏธ์ค๋ก ๊ตฌํํ ์์ด๋ค.
import { readFile } from 'fs';
export const readFilePromise = (filename: string): Promise<string> =>
new Promise<string>((
resolve: (value: string) => void,
reject: (error: Error) => void) => {
readFile(filename, (err: Error, buffer: Buffer) => {
if(err) {
reject(err);
} else {
resolve(buffer.toString());
}
})
}
)
- ๋ค์ ์ฝ๋๋
readFilePromise
ํจ์๊ฐ ๋ฐํํ๋Promise
ํ์ ๊ฐ์ฒด์then
,catch
,finally
๋ฉ์๋๋ฅผ ๋ฉ์๋ ์ฒด์ธ ํํ๋ก ์ฌ์ฉํ๋ค.
import { readFilePromise } from "./readFilePromise";
readFilePromise('./package.json')
.then((content: string) => {
console.log(content);
return readFilePromise('./tsconfig.json');
})
.then((content: string) => {
console.log(content);
return readFilePromise('.');
})
.catch((err: Error) => console.log('error: ', err.message))
.finally(() => console.log('ํ๋ก๊ทธ๋จ ์ข
๋ฃ'));
๐ Promise.resolve์ Promise.reject ๋ฉ์๋โ
Promise.resolve(๊ฐ)
ํํ๋ก ํธ์ถํ๋ฉด ํญ์ ์ด ๊ฐ์then
๋ฉ์๋์์ ์ป์ ์ ์๋ค.
Promise.resolve({ name: 'Jack', age: 32 })
.then(value => console.log(value)); // { name: 'Jack', age: 32 }
Promise.reject(Error ํ์ ๊ฐ์ฒด)
๋ฅผ ํธ์ถํ๋ฉด ์ด Error ํ์ ๊ฐ์ฒด๋ ํญ์catch
๋ฉ์๋์ ์ฝ๋ฐฑ ํจ์์์ ์ป์ ์ ์๋ค.
Promise.reject(new Error('์๋ฌ ๋ฐ์'))
.catch((err: Error) => console.log('error: ', err.message)); // error: ์๋ฌ ๋ฐ์
๐ then-์ฒด์ธโ
Promise
๊ฐ์ฒด์then
๋ฉ์๋๋ฅผ ์ฌ๋ฌ ๋ฒ ํธ์ถํ๋ ์ฝ๋ ํํ๋ฅผthen-์ฒด์ธ
์ด๋ผ๊ณ ํ๋ค.
Promise.resolve(1)
.then((value: number) => {
console.log(value); // 1
return Promise.resolve(true);
})
.then((value: boolean) => {
console.log(value); // true
return [1, 2, 3];
})
.then((value: number[]) => {
console.log(value); // [1, 2, 3]
return { name: 'jack', age: 32 };
})
.then((value: { name: string, age: number }) => {
console.log(value); // { name: 'jack', age: 32 }
})
๐Promise.all ๋ฉ์๋โ
Promise.all
๋ฉ์๋๋Promise
๊ฐ์ฒด๋ฅผ ๋ฐฐ์ด ํํ๋ก ๋ฐ์, ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋กresolve
๋ ๊ฐ๋ค์ ๋ฐฐ์ด๋ก ๋ง๋ค์ด ์ค๋ค.Promise.all
๋ฉ์๋๋ ์ด๋ฐ ๋ด์ฉ์ผ๋ก ๊ตฌ์ฑ๋ ๋ ๋ค๋ฅธPromise
๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ฏ๋ก ํด์๋ ๊ฐ๋ค์ ๋ฐฐ์ด์then
๋ฉ์๋๋ฅผ ํธ์ถํด์ ์ป๋๋ค.- ๋ง์ฝ, ๋ฐฐ์ด์ ๋ด๊ธด
Promise
๊ฐ์ฒด ์ค ๊ฑฐ์ ๊ฐ์ฒด๊ฐ ๋ฐ์ํ๋ฉด ๋ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ํด๋น ๊ฑฐ์ ๊ฐ์ ๋ด์Promise.reject
๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
const getAllResolvedResult = <T>(promises: Promise<T>[]) => Promise.all(promises);
getAllResolvedResult<any>([Promise.resolve(true), Promise.resolve('hello')])
.then(result => console.log(result)); // [true, 'hello']
getAllResolvedResult<any>([Promise.reject(new Error('error')), Promise.resolve(1)])
.then(result => console.log(result)) // ํธ์ถ๋์ง ์๋๋ค.
.catch(error => console.log('error: ', error.message)); // error: error
๐ Promise.race ๋ฉ์๋โ
Promise.race
ํด๋์ค ๋ฉ์๋๋ ๋ฐฐ์ด์ ๋ด๊ธด ํ๋ก๋ฏธ์ค ๊ฐ์ฒด ์ค ํ๋๋ผ๋resolve
๋๋ฉด ์ด ๊ฐ์ ๋ด์Promise.resolve
๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค. ๋ง์ผ ๊ฑฐ์ ๊ฐ์ด ๊ฐ์ฅ ๋จผ์ ๋ฐ์ํ๋ฉดpromise.reject
๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
Promise.race([Promise.resolve(true), Promise.resolve('hello')])
.then(value => console.log(value)); // true
Promise.race([Promise.resolve(true), Promise.reject(new Error('hello'))])
.then(value => console.log(value)) // true
.catch(error => console.log(error.message)); // ํธ์ถ๋์ง ์๋๋ค
Promise.race([Promise.reject(new Error('error')), Promise.resolve(true)])
.then(value => console.log(value)) // ํธ์ถ๋์ง ์๋๋ค
.catch(error => console.log(error.message)); // error
๐ฆ async์ await ๊ตฌ๋ฌธโ
๐ async ํจ์์ ๋ ๊ฐ์ง ์ฑ์งโ
async
ํจ์ ์์ ์๊ฐ ๋ถ์ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ ์ฑ์ง์ ๊ฐ์ง๊ณ ์๋ค.
- ์ผ๋ฐ ํจ์์ฒ๋ผ ์ฌ์ฉํ ์ ์๋ค.
Promise
๊ฐ์ฒด๋ก ์ฌ์ฉํ ์ ์๋ค.
๐ async ํจ์๊ฐ ๋ฐํํ๋ ๊ฐ์ ์๋ฏธโ
async
ํจ์๋ ๊ฐ์ ๋ฐํํ ์ ์๋ค. ์ด๋ ๋ฐํ๊ฐ์Promise
ํํ๋ก ๋ณํ๋๋ฏ๋ก ๋ค์์ฒ๋ผthen
๋ฉ์๋๋ฅผ ํธ์ถํดasync
ํจ์์ ๋ฐํ๊ฐ์ ์ป์ด์ผ ํ๋ค.
const asyncReturn = async() => {
return [1, 2, 3];
}
asyncReturn()
.then(value => console.log(value)); // [1, 2, 3]
๐ async ํจ์์ ์์ธ ์ฒ๋ฆฌโ
const asyncException = async () => {
throw new Error('error');
}
asyncException()
.catch(err => console.log('error: ', err.message)); // error: error
๐ async ํจ์์ Promise.allโ
import { readFilePromise } from "./readFilePromise"
const readFilesAll = async (fileNames: string[]) => {
return await Promise.all(
fileNames.map(fileNames => readFilePromise(fileNames))
);
}
readFilesAll(['./package.json', './tsconfig.json'])
.then(([packageJson, tsConfigJson]: string[]) => {
console.log(packageJson);
console.log(tsConfigJson);
})
.catch(err => console.log(err))