Skip to content

Commit 38cf094

Browse files
[프라미스 체이닝] 보완
1 parent d7fd76c commit 38cf094

File tree

1 file changed

+29
-29
lines changed

1 file changed

+29
-29
lines changed

1-js/11-async/03-promise-chaining/article.md

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
# 프라미스 체이닝
33

4-
<info:callbacks>에서 언급한 문제를 다시 집어봅시다. 스크립트를 불러오는 것과 같이 순차적으로 처리해야 하는 비동기 작업이 여러 개 있다고 가정해 봅시다. 이런 상황을 어떻게 하면 코드로 풀어낼 수 있을까요?
4+
<info:callbacks> 챕터에서 언급한 문제를 다시 집어봅시다. 스크립트를 불러오는 것과 같이 순차적으로 처리해야 하는 비동기 작업이 여러 개 있다고 가정해 봅시다. 어떻게 해야 이런 상황을 코드로 풀어낼 수 있을까요?
55

66
프라미스를 사용하면 여러 가지 해결책을 만들 수 있습니다.
77

@@ -35,20 +35,20 @@ new Promise(function(resolve, reject) {
3535
프라미스 체이닝은 `result``.then` 핸들러의 체인(사슬)을 통해 전달된다는 점에서 착안한 아이디어입니다.
3636

3737
위 예시는 아래와 같은 순서로 실행됩니다.
38-
1. 1초 후 최초 프라미스가 이행됩니다, -- `(*)`
39-
2. 이후 `.then` 핸들러가 호출됩니다. --`(**)`
38+
1. 1초 후 최초 프라미스가 이행됩니다. -- `(*)`
39+
2. 이후 첫번째 `.then` 핸들러가 호출됩니다. --`(**)`
4040
3. 2에서 반환한 값은 다음 `.then` 핸들러에 전달됩니다. -- `(***)`
4141
4. 이런 과정이 계속 이어집니다.
4242

4343
`result`가 핸들러 체인을 따라 전달되므로, `alert` 창엔 `1`, `2`, `4`가 순서대로 출력됩니다.
4444

4545
![](promise-then-chain.svg)
4646

47-
이렇게 프라미스 체이닝이 가능한 이유는 `promise.then`을 호출하면 프라미스가 반환되기 때문입니다. 프라미스가 반환되기 때문에 `.then`을 호출할 수 있습니다.
47+
프라미스 체이닝이 가능한 이유는 `promise.then`을 호출하면 프라미스가 반환되기 때문입니다. 반환된 프라미스엔 당연히 `.then`을 호출할 수 있습니다.
4848

49-
핸들러가 값을 반환할 땐, 이 값이 프라미스의 `result`가 됩니다. 따라서 다음 `.then`은 이 값을 이용해 호출됩니다.
49+
한편 핸들러가 값을 반환할 때엔 이 값이 프라미스의 `result`가 됩니다. 따라서 다음 `.then`은 이 값을 이용해 호출됩니다.
5050

51-
**초보자는 프라미스 하나에 `.then`을 여러 개 추가한 후, 이를 체이닝이라고 착각합니다. 하지만 이는 체이닝이 아닙니다.**
51+
**초보자는 프라미스 하나에 `.then`을 여러 개 추가한 후, 이를 체이닝이라고 착각하는 경우가 있습니다. 하지만 이는 체이닝이 아닙니다.**
5252

5353
예시:
5454
```js run
@@ -72,21 +72,21 @@ promise.then(function(result) {
7272
});
7373
```
7474

75-
위 예시에선 프라미스 하나에 여러 개의 핸들러를 등록했습니다. 이 핸들러들은 `result`를 순차적으로 전달하지 않고, 독립적으로 처리합니다.
75+
예시의 프라미스는 하나인데 여기에 등록된 핸들러는 여러 개 입니다. 이 핸들러들은 `result`를 순차적으로 전달하지 않고 독립적으로 처리합니다.
7676

77-
그림으로 표현하면 다음과 같습니다(프라미스 체이닝을 묘사한 위 그림과 비교해 보세요).
77+
그림으로 표현하면 다음과 같습니다. 프라미스 체이닝을 묘사한 위 그림과 비교해 보세요.
7878

7979
![](promise-then-many.svg)
8080

81-
동일한 프라미스에 등록된 `.then` 전체는 동일한 결과(프라미스의 `result`)를 받습니다. 따라서 위 예시를 실행하면 얼럿 창엔 전부 `1`이 출력됩니다.
81+
동일한 프라미스에 등록된 `.then` 모두는 동일한 결과(프라미스의 `result`)를 받습니다. 따라서 위 예시를 실행하면 얼럿 창엔 전부 `1`이 출력됩니다.
8282

83-
이런 식으로 한 프라미스에 여러 개의 핸들러를 등록해서 사용하는 경우는 거의 없습니다. 프라미스 체이닝이 더 많이 쓰이죠.
83+
이런 식으로 한 프라미스에 여러 개의 핸들러를 등록해서 사용하는 경우는 거의 없습니다. 프라미스는 주로 체이닝을 해서 씁니다.
8484

8585
## 프라미스 반환하기
8686

8787
`.then(handler)`에 사용된 핸들러가 프라미스를 생성하거나 반환하는 경우도 있습니다.
8888

89-
이런 경우에 이어지는 핸들러는 프라미스가 처리될 때까지 기다리다가 처리가 완료되면 그 결과를 받습니다.
89+
이 경우 이어지는 핸들러는 프라미스가 처리될 때까지 기다리다가 처리가 완료되면 그 결과를 받습니다.
9090

9191
예시:
9292

@@ -121,15 +121,15 @@ new Promise(function(resolve, reject) {
121121
```
122122

123123
예시에서 첫 번째 `.then``1`을 출력하고 `new Promise(…)`를 반환(`(*)`)합니다.
124-
1초 후 이 프라미스가 이행되고 그 결과(`resolve`의 인수인 `result * 2`)는 두 번째 `.then`으로 전달됩니다. 두 번째 핸들러(`(**)`)는 `2`를 출력하고 동일한 과정을 반복합니다.
124+
1초 후 이 프라미스가 이행되고 그 결과(`resolve`의 인수인 `result * 2`)는 두 번째 `.then`으로 전달됩니다. 두 번째 핸들러(`(**)`)는 `2`를 출력하고 동일한 과정이 반복됩니다.
125125

126126
따라서 얼럿 창엔 이전 예시와 동일하게 1, 2, 4가 차례대로 출력됩니다. 다만 얼럿 창 사이에 1초의 딜레이가 생깁니다.
127127

128-
이렇게 프라미스를 반환하는 것도 비동기 작업 체인을 만들 수 있게 합니다.
128+
이렇게 핸들러 안에서 프라미스를 반환하는 것도 비동기 작업 체이닝을 가능하게 해줍니다.
129129

130-
## 예제: loadScript
130+
## loadScript 예시 개선하기
131131

132-
위에서 배운 기능을 사용해 [이전 챕터](info:promise-basics#loadscript)에서 프라미스를 사용해 정의한 `loadScript`(스크립트를 순차적으로 불러줌)를 다시 작성해봅시다.
132+
지금까지 배운 기능을 사용해 [이전 챕터](info:promise-basics#loadscript)에서 프라미스를 사용해 정의한 `loadScript`(스크립트를 순차적으로 불러줌)를 개선해 봅시다.
133133

134134
```js run
135135
loadScript("/article/promise-chaining/one.js")
@@ -148,14 +148,14 @@ loadScript("/article/promise-chaining/one.js")
148148
});
149149
```
150150

151-
화살표 함수를 사용해 코드를 줄이는 것도 가능합니다.
151+
화살표 함수를 사용하면 다음과 같이 코드를 줄일수도 있습니다.
152152

153153
```js run
154154
loadScript("/article/promise-chaining/one.js")
155155
.then(script => loadScript("/article/promise-chaining/two.js"))
156156
.then(script => loadScript("/article/promise-chaining/three.js"))
157157
.then(script => {
158-
// 스크립트를 정상적으로 불러왔기 때문에, 스크립트 내의 함수를 호출할 수 있습니다.
158+
// 스크립트를 정상적으로 불러왔기 때문에 스크립트 내의 함수를 호출할 수 있습니다.
159159
one();
160160
two();
161161
three();
@@ -165,7 +165,7 @@ loadScript("/article/promise-chaining/one.js")
165165

166166
`loadScript`를 호출할 때마다 프라미스가 반환되고 다음 `.then`은 이 프라미스가 이행되었을 때 실행됩니다. 이후에 다음 스크립트를 로딩하기 위한 초기화가 진행됩니다. 스크립트는 이런 과정을 거쳐 순차적으로 로드됩니다.
167167

168-
체인에 더 많은 비동기 동작을 추가할 수도 있습니다. 추가 작업이 많아져도 코드가 오른쪽으로 길어지지 않고, 아래로만 증가한다는 점에 주목해 주시기 바랍니다. '멸망'의 피라미드가 만들어지지 않습니다.
168+
체인에 더 많은 비동기 동작을 추가할 수도 있는데, 추가 작업이 많아져도 코드가 오른쪽으로 길어지지 않고 아래로만 증가해서 '멸망'의 피라미드가 만들어지지 않습니다.
169169

170170
한편, 아래와 같이 각 `loadScript``.then`을 바로 붙일 수도 있습니다.
171171

@@ -190,11 +190,11 @@ loadScript("/article/promise-chaining/one.js").then(script1 => {
190190

191191

192192
````smart header="thenable"
193-
핸들러는 프라미스가 아닌 `thenable`이라 불리는 객체를 반환하기도 합니다. 메서드 `.then` 가진 객체는 모두 `thenable`객체라고 부르는데, 이 객체는 프라미스와 같은 방식으로 처리됩니다.
193+
핸들러는 프라미스가 아닌 `thenable`이라 불리는 객체를 반환하기도 합니다. `.then`이라는 메서드를 가진 객체는 모두 `thenable`객체라고 부르는데, 이 객체는 프라미스와 같은 방식으로 처리됩니다.
194194
195-
'thenable' 객체에 대한 아이디어는 서드파티 라이브러리가 '프라미스와 호환 가능한' 자체 객체를 구현할 수 있다는 점에서 나왔습니다. 이 객체들엔 자체 확장 메서드가 구현되어 있겠지만, `.then`이 있기 때문에 네이티브 프라미스와도 호환 가능합니다.
195+
'thenable' 객체에 대한 아이디어는 서드파티 라이브러리가 '프라미스와 호환 가능한' 자체 객체를 구현할 수 있다는 점에서 나왔습니다. 이 객체들엔 자체 확장 메서드가 구현되어 있겠지만 `.then`이 있기 때문에 네이티브 프라미스와도 호환 가능합니다.
196196
197-
아래는 thenable 객체에 대한 예시입니다.
197+
아래는 thenable 객체 예시입니다.
198198
199199
```js run
200200
class Thenable {
@@ -233,11 +233,11 @@ new Promise(resolve => resolve(1))
233233
let promise = fetch(url);
234234
```
235235

236-
위 코드를 실행하면 `url`에 네트워크 요청을 보내고 프라미스를 반환합니다. 원격 서버가 헤더와 함께 응답을 보내면, 프라미스는 `response` 객체와 함께 이행됩니다. 그런데 *response 전체가 완전히 다운로드되기 전*에 이행 상태가 되어버리죠.
236+
위 코드를 실행하면 `url`에 네트워크 요청을 보내고 프라미스를 반환합니다. 원격 서버가 헤더와 함께 응답을 보내면, 프라미스는 `response` 객체와 함께 이행됩니다. 그런데 이때 *response 전체가 완전히 다운로드되기 전*프라미스는 이행 상태가 되어버립니다.
237237

238-
응답 전체를 읽으려면 메서드 `response.text()`를 호출해야 합니다. `response.text()`는 원격 서버에서 전송한 텍스트 전체가 다운로드되면, 이 텍스트를 `result` 값으로 갖는 이행된 프라미스를 반환합니다.
238+
응답이 완전히 종료되고, 응답 전체를 읽으려면 메서드 `response.text()`를 호출해야 합니다. `response.text()`는 원격 서버에서 전송한 텍스트 전체가 다운로드되면, 이 텍스트를 `result` 값으로 갖는 이행된 프라미스를 반환합니다.
239239

240-
아래 코드를 실행하면 `user.json`요청을 보내고, 서버에서 해당 텍스트를 불러옵니다.
240+
아래 코드를 실행하면 `user.json`요청이 가고 서버에서 해당 텍스트를 불러옵니다.
241241

242242
```js run
243243
fetch('/article/promise-chaining/user.json')
@@ -253,7 +253,7 @@ fetch('/article/promise-chaining/user.json')
253253
});
254254
```
255255

256-
그런데 메서드 `response.json()` 를 쓰면 원격에서 받아온 데이터를 읽고, JSON으로 파싱할 수 있습니다. 예시엔 이 메서드가 더 적합하므로 기존에 작성한 코드를 약간 변경해 보겠습니다.
256+
그런데 메서드 `response.json()` 를 쓰면 원격에서 받아온 데이터를 읽고 JSON으로 파싱할 수 있습니다. 예시엔 이 메서드가 더 적합하므로 기존에 작성한 코드를 약간 변경해 보겠습니다.
257257

258258
화살표 함수도 함께 써서 코드를 간결하게 해보겠습니다.
259259

@@ -288,11 +288,11 @@ fetch('/article/promise-chaining/user.json')
288288
});
289289
```
290290

291-
코드는 주석에 적은 대로 잘 동작합니다. 그런데 위 코드엔 프로미스를 다루는데 서툰 개발자가 자주 저지르는 잠재적 문제가 내재돼 있습니다.
291+
코드는 주석에 적은 대로 잘 동작합니다. 그런데 위 코드엔 프라미스를 다루는데 서툰 개발자가 자주 저지르는 잠재적 문제가 내재돼 있습니다.
292292

293293
`(*)`로 표시한 줄을 봅시다. 만약 아바타가 잠깐 보였다가 사라진 *이후에* 무언가를 하고 싶으면 어떻게 해야 할까요? 사용자 정보를 수정할 수 있게 해주는 폼을 보여주는 것 같은 작업을 추가하는 경우같이 말이죠. 지금으로선 방법이 없습니다.
294294

295-
체인을 확장할 수 있도록 만들려면, 아바타가 사라질 때 이행 프라미스를 반환해 줘야 합니다.
295+
체인을 확장할 수 있도록 만들려면 아바타가 사라질 때 이행 프라미스를 반환해 줘야 합니다.
296296

297297
아래와 같이 말이죠.
298298

@@ -320,7 +320,7 @@ fetch('/article/promise-chaining/user.json')
320320
.then(githubUser => alert(`Finished showing ${githubUser.name}`));
321321
```
322322

323-
`(*)`로 표시한 곳의 `.then` 핸들러는 이제 `setTimeout`안의 `resolve(githubUser)`를 호출했을 때(`(**)`) 만 처리상태가 되는 `new Promise`를 반환합니다. 체인의 다음 `.then`은 이를 기다리죠.
323+
`(*)`로 표시한 곳의 `.then` 핸들러는 이제 `setTimeout`안의 `resolve(githubUser)`를 호출했을 때(`(**)`) 만 처리상태가 되는 `new Promise`를 반환합니다. 체인의 다음 `.then`은 이를 기다립니다.
324324

325325
비동기 동작은 항상 프라미스를 반환하도록 하는 것이 좋습니다. 지금은 체인을 확장할 계획이 없더라도 이렇게 구현해 놓으면 나중에 체인 확장이 필요한 경우 손쉽게 체인을 확장할 수 있습니다.
326326

@@ -361,7 +361,7 @@ loadJson('/article/promise-chaining/user.json')
361361

362362
## 요약
363363

364-
`.then` 또는 `catch/finally` 핸들러(어떤 경우도 상관없음)가 프라미스를 반환하면, 나머지 체인은 프라미스가 처리될 때까지 대기합니다. 처리가 완료되면 프라미스의 `result`(값 또는 에러)가 다음 체인으로 전달됩니다.
364+
`.then` 또는 `.catch`, `.finally` 핸들러(어떤 경우도 상관없음)가 프라미스를 반환하면, 나머지 체인은 프라미스가 처리될 때까지 대기합니다. 처리가 완료되면 프라미스의 `result`(값 또는 에러)가 다음 체인으로 전달됩니다.
365365

366366
이를 그림으로 나타내면 아래와 같습니다.
367367

0 commit comments

Comments
 (0)