diff --git a/README.md b/README.md
index 2d813e3..a3c6fdc 100644
--- a/README.md
+++ b/README.md
@@ -41,4 +41,4 @@ https://ko.javascript.info/
| 5์ฃผ์ฐจ | [๐](./daepan/5์ฃผ์ฐจ.md) | [๐](./kimeodml/5์ฃผ์ฐจ.md) | |
| 6์ฃผ์ฐจ | [๐](./daepan/6์ฃผ์ฐจ.md) | [๐](./kimeodml/6์ฃผ์ฐจ.md) | |
| 7์ฃผ์ฐจ | [๐](./daepan/7์ฃผ์ฐจ.md) | [๐](./kimeodml/7์ฃผ์ฐจ.md) | |
-| 8์ฃผ์ฐจ | [๐](./daepan/8์ฃผ์ฐจ.md) | | |
+| 8์ฃผ์ฐจ | [๐](./daepan/8์ฃผ์ฐจ.md) | [๐](./kimeodml/8์ฃผ์ฐจ.md) | |
diff --git "a/kimeodml/8\354\243\274\354\260\250.md" "b/kimeodml/8\354\243\274\354\260\250.md"
new file mode 100644
index 0000000..b89dff1
--- /dev/null
+++ "b/kimeodml/8\354\243\274\354\260\250.md"
@@ -0,0 +1,536 @@
+[1. ์ฝ๋ฐฑ](#์ฝ๋ฐฑ)
+[2. ํ๋ผ๋ฏธ์ค](#ํ๋ผ๋ฏธ์ค)
+[3. ํ๋ผ๋ฏธ์ค ์ฒด์ด๋](#ํ๋ผ๋ฏธ์ค-์ฒด์ด๋)
+[4. ํ๋ผ๋ฏธ์ค์ ์๋ฌ ํธ๋ค๋ง](#ํ๋ผ๋ฏธ์ค์-์๋ฌ-ํธ๋ค๋ง)
+[5. ํ๋ผ๋ฏธ์ค API](#ํ๋ผ๋ฏธ์ค-api)
+[6. ํ๋ผ๋ฏธ์คํ](#ํ๋ผ๋ฏธ์คํ)
+[7. ๋ง์ดํฌ๋กํ์คํฌ](#๋ง์ดํฌ๋กํ์คํฌ)
+[8. async์ await](#async์-await)
+
+---
+### ์ฝ๋ฐฑ
+- *๋น๋๊ธฐ* ๋์์ ์ค์ผ์ค๋ง ํ ์ ์์ > `์ฝ๋ฐฑ`
+ ```
+ function loadScript(src, callback) {
+ let script = document.createElement('script');
+ script.src = src;
+ script.onload = () => callback(script);
+ document.head.append(script);
+ }
+
+ loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', script => {
+ alert(`${script.src}๊ฐ ๋ก๋๋์์ต๋๋ค.`);
+ alert( _ ); // ์คํฌ๋ฆฝํธ์ ์ ์๋ ํจ์
+ });
+ ```
+ - ๋ ๋ฒ์งธ ์ธ์๋ก ์ ๋ฌ๋ ํจ์(๋๊ฐ ์ต๋ช
ํจ์)๋ ์ํ๋ ๋์์ด ์๋ฃ๋์์ ๋ ์คํ๋จ
+ - '์ฝ๋ฐฑ ๊ธฐ๋ฐ' ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ - ๋ฌด์ธ๊ฐ๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ์ํํ๋ ํจ์๋ ํจ์ ๋ด ๋์์ด ๋ชจ๋ ์ฒ๋ฆฌ๋ ํ ์คํ๋์ด์ผ ํ๋ ํจ์๊ฐ ๋ค์ด๊ฐ `์ฝ๋ฐฑ`์ ์ธ์๋ก ๋ฐ๋์ ์ ๊ณต
+ - `loadScript`์ ์ธ์๋ก ์ฝ๋ฐฑ์ ์ ๊ณต
+
+
+
+- ๋ ๊ฐ์ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฐจ์ ์ผ๋ก ๋ถ๋ฌ์ค๊ณ ์ถ์ ๋ > ์ฝ๋ฐฑ ์ค์ฒฉ
+ ```
+ loadScript('/my/script.js', function(script) {
+ alert(`${script.src}์ ๋ก๋ฉํ์ต๋๋ค. ์ด์ , ๋ค์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ก๋ฉํฉ์๋ค.`);
+
+ loadScript('/my/script2.js', function(script) {
+ alert(`๋ ๋ฒ์งธ ์คํฌ๋ฆฝํธ๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๋ก๋ฉํ์ต๋๋ค.`);
+ });
+ });
+ ```
+
+
+
+- ์ฝ๋ฐฑ์๋ฌ ์๋ฌ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ
+ ```
+ function loadScript(src, callback) {
+ let script = document.createElement('script');
+ script.src = src;
+
+ script.onload = () => callback(null, script);
+ // ์ง์ ์๋ฌ ๋์ง๊ธฐ
+ script.onerror = () => callback(new Error(`${src}๋ฅผ ๋ถ๋ฌ์ค๋ ๋์ค์ ์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค.`));
+
+ document.head.append(script);
+ }
+
+ loadScript('/my/script.js', function(error, script) {
+ // ์ค๋ฅ ์ฐ์ ์ฝ๋ฐฑ(error-first callback)
+ if (error) {
+ // ์๋ฌ ์ฒ๋ฆฌ
+ } else {
+ // ์คํฌ๋ฆฝํธ ๋ก๋ฉ์ด ์ฑ๊ณต์ ์ผ๋ก ๋๋จ
+ }
+ });
+ ```
+ 1. `callback`์ ์ฒซ ๋ฒ์งธ ์ธ์๋ ์๋ฌ๋ฅผ ์ํด ๋จ๊ฒจ๋ . ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด ์ด ์ธ์๋ฅผ ์ด์ฉํด `callback(err)`์ด ํธ์ถ
+ 2. ๋ ๋ฒ์งธ ์ธ์(ํ์ํ๋ฉด ์ธ์๋ฅผ ๋ ์ถ๊ฐํ ์ ์์)๋ ์๋ฌ๊ฐ ๋ฐ์ํ์ง ์์์ ๋๋ฅผ ์ํด ๋จ๊ฒจ๋ . ์ํ๋ ๋์์ด ์ฑ๊ณตํ ๊ฒฝ์ฐ์ `callback(null, result1, result2...)`์ด ํธ์ถ๋จ
+
+
+
+- `์ฝ๋ฐฑ`์์ ๋น๋๊ธฐ ๋์์ด ๋ง์์ง ๊ฒฝ์ฐ > ์ฝ๋ฐฑ ์ง์ฅ / ๋ฉธ๋ง์ ํผ๋ผ๋ฏธ๋ ๋ฐ์
+ ```
+ loadScript('1.js', function(error, script) {
+
+ if (error) {
+ handleError(error);
+ } else {
+ // ...
+ loadScript('2.js', function(error, script) {
+ if (error) {
+ handleError(error);
+ } else {
+ // ...
+ loadScript('3.js', function(error, script) {
+ if (error) {
+ handleError(error);
+ } else {
+ // ๋ชจ๋ ์คํฌ๋ฆฝํธ๊ฐ ๋ก๋ฉ๋ ํ, ์คํ ํ๋ฆ์ด ์ด์ด์ง๋๋ค. (*)
+ }
+ });
+
+ }
+ })
+ }
+ });
+ ```
+ - ๋
๋ฆฝ์ ์ธ ํจ์๋ฅผ ๋ง๋ค์ด์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ๋ ์กด์ฌ > ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ํจ์๋ก ๋ง๋ค์ง ๋ชปํจ > 'ํ๋ผ๋ฏธ์ค' ์ฌ์ฉ
+
+### ํ๋ผ๋ฏธ์ค
+- `promise` ์ ๋ฌธ๋ฒ ๊ตฌ์กฐ
+ ```
+ let promise = new Promise(function(resolve, reject) {
+ // executor (์ ์ ์ฝ๋, '๊ฐ์')
+ });
+ ```
+ - `new Promise`์ ์ ๋ฌ๋๋ ํจ์๋ *executor(์คํ์, ์คํ ํจ์)* ๋ผ๊ณ ๋ถ๋ฆ
+ - executor๋ `new Promise`๊ฐ ๋ง๋ค์ด์ง ๋ ์๋์ผ๋ก ์คํ๋๋๋ฐ, ๊ฒฐ๊ณผ๋ฅผ ์ต์ข
์ ์ผ๋ก ๋ง๋ค์ด๋ด๋ ์ ์ ์ฝ๋๋ฅผ ํฌํจํจ
+ - `resolve(value)` - ์ผ์ด ์ฑ๊ณต์ ์ผ๋ก ๋๋ ๊ฒฝ์ฐ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ด๋ `value`์ ํจ๊ป ํธ์ถ
+ - `reject(error)` - ์๋ฌ ๋ฐ์ ์ ์๋ฌ ๊ฐ์ฒด๋ฅผ ๋ํ๋ด๋ `error`์ ํจ๊ป ํธ์ถ
+- `new Promise` ์์ฑ์๊ฐ ๋ฐํํ๋ `promise` ๊ฐ์ฒด๋ ์๋์ ๊ฐ์ ๋ด๋ถ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง
+ - `state` - ์ฒ์์ `'pending'`(๋ณด๋ฅ)์ด์๋ค `resolve`๊ฐ ํธ์ถ๋๋ฉด `'fulfilled'`, `reject`๊ฐ ํธ์ถ๋๋ฉด `'rejected'`๋ก ๋ณํจ
+ - `result` - ์ฒ์์ `undefined`์ด์๋ค `resolve(value)`๊ฐ ํธ์ถ๋๋ฉด `value`๋ก, `reject(error)`๊ฐ ํธ์ถ๋๋ฉด `error`๋ก ๋ณํจ
+ ![[Pasted image 20240826172506.png|400]]
+
+
+
+- ํ๋ผ๋ฏธ์ค ๊ฐ์ฒด๋ executor์ ๊ฒฐ๊ณผ๋ ์๋ฌ๋ฅผ ๋ฐ์ ์๋น ํจ์๋ฅผ ์ด์ด์ฃผ๋ ์ญํ
+ - ์๋นํจ์๋ `.then`, `.catch`, `.finally` ๋ฉ์๋๋ฅผ ์ฌ์ฉํด ๋ฑ๋ก
+
+**then**
+- `.then`์ ๋ฌธ๋ฒ ๊ตฌ์กฐ
+ ```
+ promise.then(
+ function(result) { /* ๊ฒฐ๊ณผ(result)๋ฅผ ๋ค๋ฃน๋๋ค */ },
+ function(error) { /* ์๋ฌ(error)๋ฅผ ๋ค๋ฃน๋๋ค */ }
+ );
+ ```
+ - `.then`์ ์ฒซ ๋ฒ์งธ ์ธ์๋ ํ๋ผ๋ฏธ์ค๊ฐ ์ดํ๋์์ ๋ ์คํ๋๋ ํจ์์ด๊ณ , ์คํ๊ฒฐ๊ณผ๋ฅผ ๋ค๋ฃธ
+ - ๋ ๋ฒ์งธ ์ธ์๋ ํ๋ผ๋ฏธ์ค๊ฐ ๊ฑฐ๋ถ๋์์ ๋ ์คํ๋๋ ํจ์์ด๊ณ , ์๋ฌ๋ฅผ ๋ค๋ฃธ
+
+
+
+- ์ฑ๊ณต์ ์ผ๋ก ์ดํ๋ ํ๋ผ๋ฏธ์ค ์ฝ๋ ์์
+ ```
+ let promise = new Promise(function(resolve, reject) {
+ setTimeout(() => resolve("์๋ฃ!"), 1000);
+ });
+
+ // resolve ํจ์๋ .then์ ์ฒซ ๋ฒ์งธ ํจ์(์ธ์)๋ฅผ ์คํํฉ๋๋ค.
+ promise.then(
+ result => alert(result), // 1์ด ํ "์๋ฃ!"๋ฅผ ์ถ๋ ฅ
+ error => alert(error) // ์คํ๋์ง ์์
+ );
+
+ // ์ฑ๊ณต์ ์ธ ๊ฒฐ๊ณผ๋ฌผ๋ง ๋ค๋ฃจ๊ณ ์ถ์ ๊ฒฝ์ฐ
+ let promise = new Promise(resolve => {
+ setTimeout(() => resolve("์๋ฃ!"), 1000);
+ });
+
+ promise.then(alert); // 1์ด ๋ค "์๋ฃ!" ์ถ๋ ฅ
+ ```
+
+**catch**
+- ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ๋ง ๋ค๋ฃจ๊ณ ์ถ์ ๊ฒฝ์ฐ
+ - `.then(null, errorHandlingFunction)`
+ - `.catch(errorHandlingFunction)`
+ ```
+ let promise = new Promise((resolve, reject) => {
+ setTimeout(() => reject(new Error("์๋ฌ ๋ฐ์!")), 1000);
+ });
+
+ // .catch(f)๋ promise.then(null, f)๊ณผ ๋์ผํ๊ฒ ์๋ํฉ๋๋ค
+ promise.catch(alert); // 1์ด ๋ค "Error: ์๋ฌ ๋ฐ์!" ์ถ๋ ฅ
+ ```
+
+**finally**
+- ๊ฒฐ๊ณผ๊ฐ ์ด๋ป๋ ๋ง๋ฌด๋ฆฌ๊ฐ ํ์ํ๋ฉด `finally`๋ฅผ ์ฌ์ฉ
+ - `finally(f)`
+ - `.then(f,f)`
+ ```
+ new Promise((resolve, reject) => {
+ /* ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ์ด๋ค ์ผ์ ์ํํ๊ณ , ๊ทธ ํ resolve, reject๋ฅผ ํธ์ถํจ */
+ })
+ // ์ฑ๊ณตยท์คํจ ์ฌ๋ถ์ ์๊ด์์ด ํ๋ผ๋ฏธ์ค๊ฐ ์ฒ๋ฆฌ๋๋ฉด ์คํ๋จ
+ .finally(() => ๋ก๋ฉ ์ธ๋์ผ์ดํฐ ์ค์ง)
+ .then(result => result์ err ๋ณด์ฌ์ค => error ๋ณด์ฌ์ค)
+ ```
+
+
+
+- finally์ `.then(f,f)`์ ์ฐจ์ด์
+ 1. `finally` ํธ๋ค๋ฌ์ ์ธ์๊ฐ ์์. `finally`์์ ํ๋ผ๋ฏธ์ค๊ฐ ์ดํ๋์๋์ง, ๊ฑฐ๋ถ๋์๋์ง ์ ์ ์์. `finally`์์ ์ ์ฐจ๋ฅผ ๋ง๋ฌด๋ฆฌํ๋ '๋ณดํธ์ ' ๋์์ ์ํํ๊ธฐ ๋๋ฌธ์ ์ฑ๊ณตโข์คํจ ์ฌ๋ถ๋ฅผ ๋ชฐ๋ผ๋ ๋จ
+ 2. `finally` ํธ๋ค๋ฌ๋ ์๋์ผ๋ก ๋ค์ ํธ๋ค๋ฌ์ ๊ฒฐ๊ณผ์ ์๋ฌ๋ฅผ ์ ๋ฌ
+ ```
+ // ํ๋ผ๋ฏธ์ค์์ ์๋ฌ๊ฐ ๋ฐ์ํ๊ณ ์ด ์๋ฌ๊ฐ finally๋ฅผ ๊ฑฐ์ณ catch๊น์ง ์ ๋ฌ๋จ
+ new Promise((resolve, reject) => {
+ setTimeout(() => resolve("๊ฒฐ๊ณผ"), 2000)
+ })
+ .finally(() => alert("ํ๋ผ๋ฏธ์ค๊ฐ ์ค๋น๋์์ต๋๋ค."))
+ .then(result => alert(result)); // <-- .then์์ result๋ฅผ ๋ค๋ฃฐ ์ ์์
+ ```
+ - `finally`๋ ํ๋ผ๋ฏธ์ค ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ๋ง๋ค์ด์ง ๊ฒ ์๋. ํ๋ผ๋ฏธ์ค ๊ฒฐ๊ณผ๋ `finally`๋ฅผ ํตํด ์ ๋ฌ๋จ
+ 3. `.finally(f)`๋ ํจ์ `f`๋ฅผ ์ค๋ณตํด์ ์ธ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ `.then(f,f)`๋ณด๋ค ๋ฌธ๋ฒ ์ธก๋ฉด์์ ํธ๋ฆฌํจ
+
+
+
+- ํ๋ผ๋ฏธ์ค๋ฅผ ํ์ฉํ `loadScript` ์ฝ๋
+ ```
+ function loadScript(src) {
+ return new Promise(function(resolve, reject) {
+ let script = document.createElement('script');
+ script.src = src;
+
+ script.onload = () => resolve(script);
+ script.onerror = () => reject(new Error(`${src}๋ฅผ ๋ถ๋ฌ์ค๋ ๋์ค์ ์๋ฌ๊ฐ ๋ฐ์ํจ`));
+
+ document.head.append(script);
+ });
+ }
+
+ let promise = loadScript("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js");
+
+ promise.then(
+ script => alert(`${script.src}์ ๋ถ๋ฌ์์ต๋๋ค!`),
+ error => alert(`Error: ${error.message}`)
+ );
+
+ promise.then(script => alert('๋๋ค๋ฅธ ํธ๋ค๋ฌ...'));
+
+ ```
+
+### ํ๋ผ๋ฏธ์ค ์ฒด์ด๋
+- ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌํด์ผ ํ๋ ๋น๋๊ธฐ ์์
์ด ์ฌ๋ฌ ๊ฐ ์์ ๊ฒฝ์ฐ > ํ๋ผ๋ฏธ์ค ์ฒด์ด๋
+ ```
+ new Promise(function(resolve, reject) {
+ setTimeout(() => resolve(1), 1000); // (*)
+ }).then(function(result) { // (**)
+ alert(result); // 1
+ return result * 2;
+ }).then(function(result) { // (***)
+ alert(result); // 2
+ return result * 2;
+ }).then(function(result) {
+ alert(result); // 4
+ return result * 2;
+ });
+ ```
+ - `result`๊ฐ `.then` ํธ๋ค๋ฌ์ ์ฒด์ธ(์ฌ์ฌ)์ ํตํด ์ ๋ฌ๋จ
+ 1. 1์ด ํ ์ต์ด์ ํ๋ผ๋ฏธ์ค๊ฐ ์ดํ๋จ - `(*)`
+ 2. ์ดํ ์ฒซ๋ฒ์งธ `.then` ํธ๋ค๋ฌ๊ฐ ํธ์ถ - `(**)`
+ 3. 2์์ ๋ฐํํ ๊ฐ์ ๋ค์ `.then` ํธ๋ค๋ฌ์ ์ ๋ฌ - `(***)`
+ 4. ์์ ๊ฐ์ ๊ณผ์ ๋ฐ๋ณต
+
+
+
+- **ํ๋ผ๋ฏธ์ค ํ๋์ `.then`์ ์ฌ๋ฌ๊ฐ ์ถ๊ฐํ ๊ฒ์ ์ฒด์ด๋์ด ์๋**
+ ```
+ let promise = new Promise(function(resolve, reject) {
+ setTimeout(() => resolve(1), 1000);
+ });
+
+ promise.then(function(result) {
+ alert(result); // 1
+ return result * 2;
+ });
+
+ promise.then(function(result) {
+ alert(result); // 1
+ return result * 2;
+ });
+
+ promise.then(function(result) {
+ alert(result); // 1
+ return result * 2;
+ });
+ ```
+ - `result`๋ฅผ ์์ฐจ์ ์ผ๋ก ์ ๋ฌํ์ง ์๊ณ ๋
๋ฆฝ์ ์ผ๋ก ์ฒ๋ฆฌํ ๊ฒ์
+ ![[Pasted image 20240827142426.png|400]]
+ - ๋์ผํ ํ๋ผ๋ฏธ์ค์ ๋ฑ๋ก๋ `.then` ๋ชจ๋ ๋์ผํ ๊ฒฐ๊ณผ(`result`)๋ฅผ ๋ฐ์ > ์ ๋ถ `1` ์ถ๋ ฅ
+ - ์ด๋ฐ ์์ผ๋ก ํ ํ๋ผ๋ฏธ์ค์ ์ฌ๋ฌ ๊ฐ์ ํธ๋ค๋ฌ๋ฅผ ๋ฑ๋กํด์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ์์ > ์ฒด์ด๋์ผ๋ก ์จ์ผ ํจ
+
+
+
+- `.then(handler)`์ ์ฌ์ฉ๋ ํธ๋ค๋ฌ๊ฐ ํ๋ผ๋ฏธ์ค๋ฅผ ์์ฑํ๊ฑฐ๋ ๋ฐํํ๋ ๊ฒฝ์ฐ๋ ์์
+- ํธ๋ค๋ฌ๋ ํ๋ผ๋ฏธ์ค๊ฐ ์ฒ๋ฆฌ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ค๊ฐ ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋๋ฉด ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์
+ ```
+ new Promise(function(resolve, reject) {
+ setTimeout(() => resolve(1), 1000);
+ }).then(function(result) {
+ alert(result); // 1
+ return new Promise((resolve, reject) => { // (*)
+ setTimeout(() => resolve(result * 2), 1000);
+ });
+ }).then(function(result) { // (**)
+ alert(result); // 2
+ return new Promise((resolve, reject) => {
+ setTimeout(() => resolve(result * 2), 1000);
+ });
+ }).then(function(result) {
+ alert(result); // 4
+ });
+ ```
+ - ์ฒซ ๋ฒ์งธ `.then`์ `1`์ ์ถ๋ ฅํ๊ณ `new Promise(...)`๋ฅผ ๋ฐํ - `(*)`
+ - 1์ด ํ ์ด ํ๋ผ๋ฏธ์ค๊ฐ ์ดํ๋๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ ๋๋ฒ์งธ `.then`์ผ๋ก ์ ๋ฌ. ๋ ๋ฒ์งธ ํธ๋ค๋ฌ๋ `2`๋ฅผ ์ถ๋ ฅ - `(**)`
+ - ๋์ผํ ๊ณผ์ ๋ฐ๋ณต
+ => ๋์ผํ ๊ฒฐ๊ณผ๋ฌผ์ด ์ถ๋ ฅ๋์ง๋ง setTimeout์ ์ํด 1์ด์ ๋๋ ์ด๊ฐ ์๊น
+
+
+
+- `.then`์ ์ฌ์ฉํด `loadScript` ๊ฐ์
+ ```
+ loadScript("/article/promise-chaining/one.js")
+ .then(script => loadScript("/article/promise-chaining/two.js"))
+ .then(script => loadScript("/article/promise-chaining/three.js"))
+ .then(script => {
+ // ์คํฌ๋ฆฝํธ๋ฅผ ์ ์์ ์ผ๋ก ๋ถ๋ฌ์๊ธฐ ๋๋ฌธ์ ์คํฌ๋ฆฝํธ ๋ด์ ํจ์๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
+ one();
+ two();
+ three();
+ });
+ ```
+
+### ํ๋ผ๋ฏธ์ค์ ์๋ฌ ํธ๋ค๋ง
+- ํ๋ผ๋ฏธ์ค๊ฐ ๊ฑฐ๋ถ๋๋ฉด ์ ์ด ํ๋ฅด๋ฏธ์ด ์ ์ผ ๊ฐ๊น์ด rejection ํธ๋ค๋ฌ๋ก ๋์ด๊ฐ > `.catch`์์ ์๋ฌ ์ฒ๋ฆฌ
+ ```
+ fetch('/article/promise-chaining/user.json')
+ .then(response => response.json())
+ .then(user => fetch(`https://api.github.com/users/${user.name}`))
+ .then(response => response.json())
+ .then(githubUser => new Promise((resolve, reject) => {
+ let img = document.createElement('img');
+ img.src = githubUser.avatar_url;
+ img.className = "promise-avatar-example";
+ document.body.append(img);
+
+ setTimeout(() => {
+ img.remove();
+ resolve(githubUser);
+ }, 3000);
+ }))
+ .catch(error => alert(error.message));
+ ```
+
+
+
+- `throw` ํธ๋ค๋ฌ๋ฅผ ํตํด ์๋ฌ๋ฅผ ๋์ง ์ ์์
+ ```
+ new Promise((resolve, reject) => {
+ resolve("OK");
+ }).then((result) => {
+ throw new Error("์๋ฌ ๋ฐ์!"); // ํ๋ผ๋ฏธ์ค๊ฐ ๊ฑฐ๋ถ๋จ
+ }).catch(alert); // Error: ์๋ฌ ๋ฐ์!
+ ```
+
+
+
+- ํ๋ผ๋ฏธ์ค๋ ์ ์ฌํ๊ฒ `try..catch` ์ฒ๋ผ ์ฒ๋ฆฌํ ์ ์๋ ์๋ฌ๋ผ ํ๋จ๋๋ฉด ์๋ฌ๋ฅผ ๋ค์ ๋์ง ์ ์์
+ ```
+ // ์คํ ์์: catch -> catch
+ new Promise((resolve, reject) => {
+ throw new Error("์๋ฌ ๋ฐ์!");
+ }).catch(function(error) { // (*)
+ if (error instanceof URIError) {
+ // ์๋ฌ ์ฒ๋ฆฌ
+ } else {
+ alert("์ฒ๋ฆฌํ ์ ์๋ ์๋ฌ");
+ throw error; // ์๋ฌ ๋ค์ ๋์ง๊ธฐ
+ }
+ }).then(function() {
+ /* ์ฌ๊ธฐ๋ ์คํ๋์ง ์์ต๋๋ค. */
+ }).catch(error => { // (**)
+ alert(`์ ์ ์๋ ์๋ฌ๊ฐ ๋ฐ์ํจ: ${error}`);
+ // ๋ฐํ๊ฐ์ด ์์ => ์คํ์ด ๊ณ์๋จ
+ });
+ ```
+ - `(*)`์์ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ์ง ๋ชป ํ๊ธฐ ๋๋ฌธ์ ์๋ฌ๋ฅผ ๋ค์ ๋์ง
+
+### ํ๋ผ๋ฏธ์ค API
+**Pormise.all**
+- ๋ชจ๋ ํ๋ผ๋ฏธ์ค๊ฐ ์ดํ๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๊ทธ ๊ฒฐ๊ด๊ฐ์ ๋ด์ ๋ฐฐ์ด์ ๋ฐํ
+- **์ฃผ์ด์ง ํ๋ผ๋ฏธ์ค ์ค ํ๋๋ผ๋ ์คํจํ๋ฉด `Promise.all`์ ๊ฑฐ๋ถ๋๊ณ , ๋๋จธ์ง ํ๋ผ๋ฏธ์ค์ ๊ฒฐ๊ณผ๋ ๋ฌด์๋จ**
+ ```
+ Promise.all([
+ new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
+ new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
+ new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
+ ]).then(alert); // ํ๋ผ๋ฏธ์ค ์ ์ฒด๊ฐ ์ฒ๋ฆฌ๋๋ฉด 1, 2, 3์ด ๋ฐํ๋ฉ๋๋ค. ๊ฐ ํ๋ผ๋ฏธ์ค๋ ๋ฐฐ์ด์ ๊ตฌ์ฑํ๋ ์์๊ฐ ๋ฉ๋๋ค.
+ ```
+
+**Promise.allSettled**
+- ํ๋ผ๋ฏธ์ค๊ฐ ์ฒ๋ฆฌ๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ด์ ๋ฐฐ์ด์ ๋ฐํ
+ - ์๋ต ์ฑ๊ณต - `{status:'fulfilled', value:result}`
+ - ์๋ต ์คํจ - `{status:'rejected', reason:error}`
+ ```
+ let urls = [
+ 'https://api.github.com/users/iliakan',
+ 'https://api.github.com/users/Violet-Bora-Lee',
+ 'https://no-such-url'
+ ];
+
+ Promise.allSettled(urls.map(url => fetch(url)))
+ .then(results => { // (*)
+ results.forEach((result, num) => {
+ if (result.status == "fulfilled") {
+ alert(`${urls[num]}: ${result.value.status}`);
+ }
+ if (result.status == "rejected") {
+ alert(`${urls[num]}: ${result.reason}`);
+ }
+ });
+ });
+
+ // ์๋ต ๊ฒฐ๊ณผ (๊ฐ ๋๋ ์๋ฌ์ ๊ฒฐ๊ด๊ฐ์ ๋ฐ์)
+ [
+ {status: 'fulfilled', value: ...์๋ต...},
+ {status: 'fulfilled', value: ...์๋ต...},
+ {status: 'rejected', reason: ...์๋ฌ ๊ฐ์ฒด...}
+ ]
+ ```
+
+**Promise.race**
+- ๊ฐ์ฅ ๋จผ์ ์ฒ๋ฆฌ๋ ํ๋ผ๋ฏธ์ค์ ๊ฒฐ๊ณผ ๋๋ ์๋ฌ๋ฅผ ๋ด์ ํ๋ผ๋ฏธ์ค๋ฅผ ๋ฐํ
+ ```
+ Promise.race([
+ new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
+ new Promise((resolve, reject) => setTimeout(() => reject(new Error("์๋ฌ ๋ฐ์!")), 2000)),
+ new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
+ ]).then(alert); // 1
+ ```
+
+**Promise.resolve**
+- Promise.resolve - ์ฃผ์ด์ง ๊ฐ์ ์ฌ์ฉํด ์ดํ ์ํ์ ํ๋ผ๋ฏธ์ค๋ฅผ ๋ง๋ฆ
+- Promise.reject - ์ฃผ์ด์ง ์๋ฌ๋ฅผ ์ฌ์ฉํด ๊ฑฐ๋ถ ์ํ์ ํ๋ผ๋ฏธ์ค๋ฅผ ๋ง๋ฆ
+- async/await์ด ๋์ ํ๊ฒ ๋์์
+
+### ํ๋ผ๋ฏธ์คํ
+- ์ฝ๋ฐฑ์ ๋ฐ๋ ํจ์๋ฅผ ํ๋ผ๋ฏธ์ค๋ฅผ ๋ฐํํ๋ ํจ์๋ก ๋ฐ๊พธ๋ ๊ฒ์ 'ํ๋ผ๋ฏธ์คํ'๋ผ๊ณ ํจ
+- ์ฝ๋ฐฑ๋ณด๋ค ํ๋ผ๋ฏธ์ค๊ฐ ํธ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ์ฝ๋ฐฑ ๊ธฐ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ๋ผ๋ฏธ์ค๋ฅผ ๋ฐํํ๋ ํจ์๋ก ๋ฐ๊พธ๋ ๊ฒ ์ข์ ๊ฒฝ์ฐ๊ฐ ์ข
์ข
์์
+- `loadScript(src, callback)`๋ฅผ ํ๋ผ๋ฏธ์คํํ๊ธฐ
+ ```
+ // Before
+ function loadScript(src, callback) {
+ let script = document.createElement('script');
+ script.src = src;
+
+ script.onload = () => callback(null, script);
+ script.onerror = () => callback(new Error(`${src}๋ฅผ ๋ถ๋ฌ์ค๋ ๋์ค์ ์๋ฌ๊ฐ ๋ฐ์ํจ`));
+
+ document.head.append(script);
+ }
+
+ // ์ฌ์ฉ๋ฒ:
+ // loadScript('path/script.js', (err, script) => {...})
+
+ // After
+ let loadScriptPromise = function(src) {
+ return new Promise((resolve, reject) => {
+ loadScript(src, (err, script) => { // callback์ ์ ์ธํ src ์ธ์๋ง ํ์ + Promise๋ฅผ ๋ฐํ
+ if (err) reject(err)
+ else resolve(script);
+ });
+ })
+ }
+
+ // ์ฌ์ฉ๋ฒ:
+ // loadScriptPromise('path/script.js').then(...)
+ ```
+ - `loadScriptPromsie`๋ ๊ธฐ์กด ํจ์ `loadScirpt`์ ๋ชจ๋ ์ผ์ ์์ํจ
+ - `loadScript`์ ์ฝ๋ฐฑ์ ์คํฌ๋ฆฝํธ ๋ก๋ฉ ์ํ์ ๋ฐ๋ผ `์ดํ(fulfilled)` ํน์ `๊ฑฐ๋ถ(rejected)` ์ํ์ ํ๋ผ๋ฏธ์ค๋ฅผ ๋ฐํ
+
+### ๋ง์ดํฌ๋กํ์คํฌ
+- ํ๋ผ๋ฏธ์ค ํธ๋ค๋ฌ `.then/catch/finally`๋ ํญ์ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ
+- ํ๋ผ๋ฏธ์ค๊ฐ ์ฆ์ ์ดํ๋๋๋ผ๋ `.then/catch/finally` *์๋*์ ์๋ ์ฝ๋๋ ์ด ํธ๋ค๋ฌ๋ค์ด ์คํ๋๊ธฐ ์ ์ ์คํ๋จ
+ ```
+ // '์ฝ๋ ์ข
๋ฃ!' -> 'ํ๋ผ๋ฏธ์ค ์ฑ๊ณต!'
+ let promise = Promise.resolve();
+
+ promise.then(() => alert("ํ๋ผ๋ฏธ์ค ์ฑ๊ณต!"));
+ alert("์ฝ๋ ์ข
๋ฃ"); // ์ผ๋ฟ ์ฐฝ์ด ๊ฐ์ฅ ๋จผ์ ๋น๋๋ค.
+ ```
+
+- ๋น๋๊ธฐ ์์
์ ์ฒ๋ฆฌํ๋ ค๋ฉด ์ ์ ํ ๊ด๋ฆฌ๊ฐ ํ์ > '๋ง์ดํฌ๋กํ์คํฌ ํ'์์ ๊ด๋ฆฌ
+ - ๋ง์ดํฌ๋กํ์คํฌ ํ๋ ๋จผ์ ๋ค์ด์จ ์์
์ ๋จผ์ ์คํํจ(FIFO)
+ - ์คํํ ๊ฒ์ด ์๋ฌด๊ฒ๋ ๋จ์ง ์์ ๋๋ง ๋ง์ดํฌ๋กํ์คํฌ ํ์ ์๋ ์์
์ด ์คํ๋จ
+- ์ด๋ค ํ๋ผ๋ฏธ์ค๊ฐ ์ค๋น๋์์ ๋ ์ด ํ๋ผ๋ฏธ์ค์ `.then/catch/finally` ํธ๋ค๋ฌ๊ฐ ํ์ ๋ค์ด๊ฐ๋ค๊ณ ์๊ฐํ์๋ฉด ๋จ. ์ด๋ ํธ๋ค๋ฌ๋ ์ฌ์ ํ ์คํ๋์ง ์์. ํ์ฌ ์ฝ๋์์ ์์ ๋ก์ด ์ํ๊ฐ ๋์์ ๋์์ธ์ดใ
์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ํ์์ ์์
์ ๊บผ๋ด ์คํํจ < '์ฝ๋ ์ข
๋ก'๊ฐ ๋จผ์ ์ถ๋ ฅ๋๋ ์ด์
+ ![[Pasted image 20240829131519.png|400]]
+
+
+
+- ํ๋ผ๋ฏธ์ค ํธ๋ค๋ฌ๋ ํญ์ ๋ด๋ถ ํ๋ฅผ ํต๊ณผํจ
+- ์ฌ๋ฌ ๊ฐ์ `.then/catch/finally`๋ฅผ ์ฌ์ฉํด ๋ง๋ ์ฒด์ธ์ ๊ฒฝ์ฐ, ๊ฐ ํธ๋ค๋ฌ๋ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋จ. ํ์ ๋ค์ด๊ฐ ํธ๋ค๋ฌ ๊ฐ๊ฐ์ ํ์ฌ ์ฝ๋๊ฐ ์๋ฃ๋๊ณ , ํ์ ์ ์ ๋ ์ด์ ํธ๋ค๋ฌ์ ์คํ์ด ์๋ฃ๋์์ ๋ ์คํ๋จ
+- **'ํ๋ผ๋ฏธ์ค ์ฑ๊ณต!'์ ๋จผ์ , '์ฝ๋ ์ข
๋ฃ'๋ฅผ ๋์ค์ ์ถ๋ ฅ๋๊ฒ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ๋?'** > `.then`์ ์ฌ์ฉํด ํ์ ๋ฃ๊ธฐ
+ ```
+ Promise.resolve()
+ .then(() => alert("ํ๋ผ๋ฏธ์ค ์ฑ๊ณต!"))
+ .then(() => alert("์ฝ๋ ์ข
๋ฃ"));
+ ```
+
+### async์ await
+- function ์์ `async`๋ฅผ ๋ถ์ด๋ฉด ํด๋น ํจ์๋ ํญ์ ํ๋ผ๋ฏธ์ค๋ฅผ ๋ฐํ
+- `await`์ ํ๋ผ๋ฏธ์ค๊ฐ ์ฒ๋ฆฌ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆผ
+- [ํ๋ผ๋ฏธ์ค ์ฒด์ด๋](https://ko.javascript.info/promise-chaining)ย ์ฑํฐ์ย `showAvatar()`ย ์์๋ฅผย `async/await`๋ก ์์ฑ
+ 1. `.then` ํธ์ถ์ `await`์ผ๋ก ๋ณ๊ฒฝ
+ 2. function ์์ `async`๋ฅผ ๋ถ์ฌ `await`๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํจ
+ ```
+ async function showAvatar() {
+ // JSON ์ฝ๊ธฐ
+ let response = await fetch('/article/promise-chaining/user.json');
+ let user = await response.json();
+
+ // github ์ฌ์ฉ์ ์ ๋ณด ์ฝ๊ธฐ
+ let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
+ let githubUser = await githubResponse.json();
+
+ // ์๋ฐํ ๋ณด์ฌ์ฃผ๊ธฐ
+ let img = document.createElement('img');
+ img.src = githubUser.avatar_url;
+ img.className = "promise-avatar-example";
+ document.body.append(img);
+
+ // 3์ด ๋๊ธฐ
+ await new Promise((resolve, reject) => setTimeout(resolve, 3000));
+ img.remove();
+ return githubUser;
+ }
+
+ showAvatar();
+ ```
+
+
+
+- `try..catch`๋ฅผ ์ฌ์ฉํด ์๋ฌ ํธ๋ค๋ง
+ ```
+ async function f() {
+ try {
+ let response = await fetch('http://์ ํจํ์ง-์์-์ฃผ์');
+ let user = await response.json();
+ } catch(err) {
+ // fetch์ response.json์์ ๋ฐํํ ์๋ฌ ๋ชจ๋๋ฅผ ์ฌ๊ธฐ์ ์ก์ต๋๋ค.
+ alert(err); // TypeError: failed to fetch
+ }
+ }
+
+ f();
+ ```
\ No newline at end of file