Skip to content

Commit 09f7b41

Browse files
committed
[프라미스 기초] upstream 병합 충돌 해결
1 parent 15cf21d commit 09f7b41

1 file changed

Lines changed: 41 additions & 138 deletions

File tree

1-js/11-async/02-promise-basics/article.md

Lines changed: 41 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
11
# 프라미스
22

3-
<<<<<<< HEAD
4-
본인을 아주 유명한 가수라고 가정해 봅시다. 그리고 탑 가수인 본인이 밤, 낮으로 다음 싱글 앨범이 언제 나오는지 물어보는 팬들을 상대해야 한다고 해 봅시다.
5-
=======
6-
Imagine that you're a top singer, and fans ask day and night for your upcoming song.
7-
>>>>>>> upstream/master
3+
본인을 아주 유명한 가수라고 가정해 봅시다. 그리고 탑 가수인 본인이 밤, 낮으로 다음 곡이 언제 나오는지 물어보는 팬들을 상대해야 한다고 해 봅시다.
84

95
당신은 앨범이 출시되면 팬들이 자동으로 소식을 받아볼 수 있도록 해 부하를 덜 겁니다. 구독 리스트를 하나 만들어 팬들에게 전달해 이메일 주소를 적게 하고, 앨범이 준비되면 리스트에 있는 팬들에게 메일을 보내 앨범 관련 소식을 바로 받아볼 수 있게 하는 식으로 말이죠. 이렇게 하면 녹음 스튜디오에 화재가 발생해서 출시 예정인 앨범이 취소되는 불상사가 발생해도 관련 소식을 팬들에게 전달 할 수 있습니다.
106

11-
<<<<<<< HEAD
12-
이제 모두가 행복해졌습니다. 밤낮으로 질문을 하는 팬이 사라졌고, 팬들은 앨범 출시를 놓치지 않을 수 있게 되었으니까요.
13-
=======
14-
Everyone is happy: you, because the people don't crowd you anymore, and fans, because they won't miss the song.
15-
>>>>>>> upstream/master
7+
이제 모두가 행복해졌습니다. 밤낮으로 질문을 하는 팬이 사라졌고, 팬들은 새 곡 출시를 놓치지 않을 수 있게 되었으니까요.
168

179
이 비유는 코드를 작성하면서 자주 만나는 상황을 실제 일어날 법한 일로 바꾼 것입니다. 바로 아래 같은 상황 말이죠.
1810

@@ -36,27 +28,15 @@ executor의 인수 `resolve`와 `reject`는 자바스크립트에서 자체 제
3628

3729
대신 executor에선 결과를 즉시 얻든 늦게 얻든 상관없이 상황에 따라 인수로 넘겨준 콜백 중 하나를 반드시 호출해야 합니다.
3830

39-
<<<<<<< HEAD
4031
- `resolve(value)` — 일이 성공적으로 끝난 경우 그 결과를 나타내는 `value`와 함께 호출
4132
- `reject(error)` — 에러 발생 시 에러 객체를 나타내는 `error`와 함께 호출
4233

4334
요약하면 다음과 같습니다. executor는 자동으로 실행되는데 여기서 원하는 일이 처리됩니다. 처리가 끝나면 executor는 처리 성공 여부에 따라 `resolve``reject`를 호출합니다.
44-
=======
45-
- `resolve(value)` — if the job is finished successfully, with result `value`.
46-
- `reject(error)` — if an error has occurred, `error` is the error object.
47-
48-
So to summarize: the executor runs automatically and attempts to perform a job. When it is finished with the attempt, it calls `resolve` if it was successful or `reject` if there was an error.
49-
>>>>>>> upstream/master
5035

5136
한편, `new Promise` 생성자가 반환하는 `promise` 객체는 다음과 같은 내부 프로퍼티를 갖습니다.
5237

53-
<<<<<<< HEAD
54-
- `state` — 처음엔 `"pending"`(보류)이었다 `resolve`가 호출되면 `"fulfilled"`, `reject`가 호출되면 `"rejected"`로 변합니다.
55-
- `result` — 처음엔 `undefined`이었다 `resolve(value)`가 호출되면 `value`로, `reject(error)`가 호출되면 `error`로 변합니다.
56-
=======
57-
- `state` — initially `"pending"`, then changes to either `"fulfilled"` when `resolve` is called or `"rejected"` when `reject` is called.
58-
- `result` — initially `undefined`, then changes to `value` when `resolve(value)` is called or `error` when `reject(error)` is called.
59-
>>>>>>> upstream/master
38+
- `state` — 처음엔 `"pending"`(보류)이었다가 `resolve`가 호출되면 `"fulfilled"`, `reject`가 호출되면 `"rejected"`로 변합니다.
39+
- `result` — 처음엔 `undefined`이었다가 `resolve(value)`가 호출되면 `value`로, `reject(error)`가 호출되면 `error`로 변합니다.
6040

6141
따라서 executor는 아래 그림과 같이 `promise`의 상태를 둘 중 하나로 변화시킵니다.
6242

@@ -80,11 +60,7 @@ let promise = new Promise(function(resolve, reject) {
8060
1. executor는 `new Promise`에 의해 자동으로 그리고 즉각적으로 호출됩니다.
8161
2. executor는 인자로 `resolve``reject` 함수를 받습니다. 이 함수들은 자바스크립트 엔진이 미리 정의한 함수이므로 개발자가 따로 만들 필요가 없습니다. 다만, `resolve``reject` 중 하나는 반드시 호출해야 합니다.
8262

83-
<<<<<<< HEAD
8463
executor '처리'가 시작 된 지 1초 후, `resolve("완료")`이 호출되고 결과가 만들어집니다. 이때 `promise` 객체의 상태는 다음과 같이 변합니다.
85-
=======
86-
After one second of "processing", the executor calls `resolve("done")` to produce the result. This changes the state of the `promise` object:
87-
>>>>>>> upstream/master
8864

8965
![](promise-resolve-1.svg)
9066

@@ -151,15 +127,9 @@ let promise = new Promise(function(resolve, reject) {
151127
프라미스 객체의 `state`, `result` 프로퍼티는 내부 프로퍼티이므로 개발자가 직접 접근할 수 없습니다. `.then`/`.catch`/`.finally` 메서드를 사용하면 접근 가능한데, 자세한 내용은 아래에서 살펴보겠습니다.
152128
```
153129
154-
<<<<<<< HEAD
155-
## 소비자: then, catch, finally
156-
157-
프라미스 객체는 executor('제작 코드' 혹은 '가수')와 결과나 에러를 받을 소비 함수('팬')를 이어주는 역할을 합니다. 소비함수는 `.then`, `.catch`, `.finally` 메서드를 사용해 등록(구독)됩니다.
158-
=======
159-
## Consumers: then, catch
130+
## 소비자: then, catch
160131
161-
A Promise object serves as a link between the executor (the "producing code" or "singer") and the consuming functions (the "fans"), which will receive the result or error. Consuming functions can be registered (subscribed) using the methods `.then` and `.catch`.
162-
>>>>>>> upstream/master
132+
프라미스 객체는 executor('제작 코드' 혹은 '가수')와 결과나 에러를 받을 소비 함수('팬')를 이어주는 역할을 합니다. 소비함수는 `.then`, `.catch` 메서드를 사용해 등록(구독)됩니다.
163133
164134
### then
165135
@@ -174,15 +144,9 @@ promise.then(
174144
);
175145
```
176146
177-
<<<<<<< HEAD
178147
`.then`의 첫 번째 인수는 프라미스가 이행되었을 때 실행되는 함수이고, 여기서 실행 결과를 받습니다.
179148
180149
`.then`의 두 번째 인수는 프라미스가 거부되었을 때 실행되는 함수이고, 여기서 에러를 받습니다.
181-
=======
182-
The first argument of `.then` is a function that runs when the promise is resolved and receives the result.
183-
184-
The second argument of `.then` is a function that runs when the promise is rejected and receives the error.
185-
>>>>>>> upstream/master
186150
187151
아래 예시는 성공적으로 이행된 프라미스에 어떻게 반응하는지 보여줍니다.
188152
@@ -252,128 +216,78 @@ promise.catch(alert); // 1초 뒤 "Error: 에러 발생!" 출력
252216
253217
`try {...} catch {...}`에 finally 절이 있는 것처럼, 프라미스에도 `finally`가 있습니다.
254218
255-
<<<<<<< HEAD
256219
프라미스가 처리되면(이행이나 거부) `f`가 항상 실행된다는 점에서 `.finally(f)` 호출은 `.then(f, f)`과 유사합니다.
257220
221+
`finally`의 목적은 이전 작업이 완료된 후 정리/마무리 작업을 수행하는 핸들러를 설정하는 것입니다.
222+
258223
쓸모가 없어진 로딩 인디케이터(loading indicator)를 멈추는 경우같이, 결과가 어떻든 마무리가 필요하면 `finally`가 유용합니다.
259224
260-
사용법은 아래와 같습니다.
225+
예를 들면 로딩 인디케이터를 멈추거나 더 이상 필요 없는 연결을 닫는 작업 등이 있습니다.
226+
227+
파티 뒷정리 담당자라고 생각해보세요. 파티가 즐거웠든 아니든, 친구가 얼마나 왔든 상관없이 파티가 끝나면 뒷정리는 해야 하니까요.
228+
229+
코드는 아래와 같은 형태가 됩니다.
261230
262231
```js
263232
new Promise((resolve, reject) => {
264-
/* 시간이 걸리는 어떤 일을 수행하고, 그 후 resolve, reject를 호출함 */
233+
/* 시간이 걸리는 작업을 수행한 후 resolve 또는 reject를 호출 */
265234
})
266235
*!*
267236
// 성공·실패 여부와 상관없이 프라미스가 처리되면 실행됨
268237
.finally(() => 로딩 인디케이터 중지)
269-
=======
270-
The call `.finally(f)` is similar to `.then(f, f)` in the sense that `f` runs always, when the promise is settled: be it resolve or reject.
271-
272-
The idea of `finally` is to set up a handler for performing cleanup/finalizing after the previous operations are complete.
273-
274-
E.g. stopping loading indicators, closing no longer needed connections, etc.
275-
276-
Think of it as a party finisher. Irresepective of whether a party was good or bad, how many friends were in it, we still need (or at least should) do a cleanup after it.
277-
278-
The code may look like this:
238+
// 다음 단계로 넘어가기 전에 로딩 인디케이터는 항상 중지됨
279239
280-
```js
281-
new Promise((resolve, reject) => {
282-
/* do something that takes time, and then call resolve or maybe reject */
283-
})
284-
*!*
285-
// runs when the promise is settled, doesn't matter successfully or not
286-
.finally(() => stop loading indicator)
287-
// so the loading indicator is always stopped before we go on
288-
>>>>>>> upstream/master
289240
*/!*
290241
.then(result => result와 err 보여줌 => error 보여줌)
291242
```
292243
293-
<<<<<<< HEAD
294244
그런데 finally는 `.then(f, f)`과 완전히 같진 않습니다. 차이점은 다음과 같습니다.
295245
296-
1. `finally` 핸들러엔 인수가 없습니다. `finally`에선 프라미스가 이행되었는지, 거부되었는지 알 수 없습니다. `finally`에선 절차를 마무리하는 '보편적' 동작을 수행하기 때문에 성공·실패 여부를 몰라도 됩니다.
297-
2. `finally` 핸들러는 자동으로 다음 핸들러에 결과와 에러를 전달합니다.
246+
1. `finally` 핸들러에는 인수가 없습니다. `finally`에서는 프라미스가 이행되었는지 거부되었는지 알 수 없습니다. 하지만 이는 문제가 되지 않습니다. `finally`의 목적은 보통 '공통적인' 마무리 작업을 수행하는 것이기 때문입니다.
298247
299-
result가 `finally`를 거쳐 `then`까지 전달되는 것을 확인해봅시다.
300-
```js run
301-
new Promise((resolve, reject) => {
302-
setTimeout(() => resolve("결과"), 2000)
303-
})
304-
.finally(() => alert("프라미스가 준비되었습니다."))
305-
.then(result => alert(result)); // <-- .then에서 result를 다룰 수 있음
306-
```
248+
위 예시를 보면 `finally` 핸들러에는 인수가 없습니다. 프라미스 결과는 다음 핸들러에서 처리됩니다.
307249
308-
프라미스에서 에러가 발생하고 이 에러가 `finally`를 거쳐 `catch`까지 전달되는 것을 확인해봅시다.
309-
=======
310-
Please note that `finally(f)` isn't exactly an alias of `then(f,f)` though.
311-
312-
There are important differences:
313-
314-
1. A `finally` handler has no arguments. In `finally` we don't know whether the promise is successful or not. That's all right, as our task is usually to perform "general" finalizing procedures.
315-
316-
Please take a look at the example above: as you can see, the `finally` handler has no arguments, and the promise outcome is handled by the next handler.
317-
2. A `finally` handler "passes through" the result or error to the next suitable handler.
318-
319-
For instance, here the result is passed through `finally` to `then`:
250+
2. `finally` 핸들러는 결과와 에러를 다음 핸들러로 그대로 전달합니다.
320251
252+
result가 `finally`를 거쳐 `then`까지 전달되는 것을 확인해봅시다.
321253
```js run
322254
new Promise((resolve, reject) => {
323-
setTimeout(() => resolve("value"), 2000);
255+
setTimeout(() => resolve(""), 2000)
324256
})
325-
.finally(() => alert("Promise ready")) // triggers first
326-
.then(result => alert(result)); // <-- .then shows "value"
257+
.finally(() => alert("프라미스가 준비되었습니다.")) // 가장 먼저 실행
258+
.then(result => alert(result)); // <-- .then이 "value" 출력
327259
```
328260
329-
As you can see, the `value` returned by the first promise is passed through `finally` to the next `then`.
261+
보다시피 첫 번째 프라미스가 반환한 `value``finally`를 거쳐 다음 `then`으로 전달됩니다.
330262
331-
That's very convenient, because `finally` is not meant to process a promise result. As said, it's a place to do generic cleanup, no matter what the outcome was.
263+
이는 매우 편리한 동작입니다. `finally`는 프라미스 결과를 처리하기 위한 메서드가 아니기 때문입니다. 앞서 설명했듯 결과와 관계없이 공통적인 정리 작업을 수행하는 곳입니다.
332264
333-
And here's an example of an error, for us to see how it's passed through `finally` to `catch`:
334-
>>>>>>> upstream/master
265+
아래는 에러가 `finally`를 거쳐 `catch`로 전달되는 예시입니다.
335266
336267
```js run
337268
new Promise((resolve, reject) => {
338269
throw new Error("에러 발생!");
339270
})
340-
<<<<<<< HEAD
341-
.finally(() => alert("프라미스가 준비되었습니다."))
342-
.catch(err => alert(err)); // <-- .catch에서 에러 객체를 다룰 수 있음
343-
```
344271
345-
`finally`는 프라미스 결과를 처리하기 위해 만들어 진 게 아닙니다. 프라미스 결과는 `finally`를 통과해서 전달되죠. 이런 특징은 아주 유용하게 사용되기도 합니다.
346-
347-
프라미스 체이닝과 핸들러 간 결과 전달에 대해선 다음 챕터에서 더 이야기 나누도록 하겠습니다.
348-
349-
3. `.finally(f)`는 함수 `f`를 중복해서 쓸 필요가 없기 때문에 `.then(f, f)`보다 문법 측면에서 더 편리합니다.
350-
351-
````smart header="처리된 프라미스의 핸들러는 즉각 실행됩니다."
352-
프라미스가 대기 상태일 때, `.then/catch/finally` 핸들러는 프라미스가 처리되길 기다립니다. 반면, 프라미스가 이미 처리상태라면 핸들러가 즉각 실행됩니다.
353-
=======
354-
.finally(() => alert("Promise ready")) // triggers first
355-
.catch(err => alert(err)); // <-- .catch shows the error
272+
.finally(() => alert("프라미스가 준비되었습니다.")) // 먼저 실행됨
273+
.catch(err => alert(err)); // <-- .catch에서 에러를 출력함
356274
```
357275
358-
3. A `finally` handler also shouldn't return anything. If it does, the returned value is silently ignored.
359-
360-
The only exception to this rule is when a `finally` handler throws an error. Then this error goes to the next handler, instead of any previous outcome.
276+
3. `finally` 핸들러는 아무것도 반환하지 않아야 합니다. 무언가를 반환하더라도 반환값은 무시됩니다.
277+
단, `finally` 핸들러에서 에러를 던지는 경우는 예외입니다. 이 경우 에러는 이전 결과 대신 다음 핸들러로 전달됩니다.
361278
362-
To summarize:
279+
요약하면 다음과 같습니다.
363280
364-
- A `finally` handler doesn't get the outcome of the previous handler (it has no arguments). This outcome is passed through instead, to the next suitable handler.
365-
- If a `finally` handler returns something, it's ignored.
366-
- When `finally` throws an error, then the execution goes to the nearest error handler.
281+
- `finally` 핸들러는 이전 핸들러의 결과를 받지 않습니다(인수가 없습니다). 결과는 대신 다음 적절한 핸들러로 전달됩니다.
282+
- `finally` 핸들러가 무언가를 반환하면 무시됩니다.
283+
- `finally`에서 에러가 발생하면 가장 가장 가까운 에러 핸들러로 전달됩니다.
367284
368-
These features are helpful and make things work just the right way if we use `finally` how it's supposed to be used: for generic cleanup procedures.
285+
이런 특징 덕분에 `finally`를 원래 목적대로 공통적인 정리 작업에 사용한다면 모든 것이 올바르게 동작합니다.
369286
370-
````smart header="We can attach handlers to settled promises"
371-
If a promise is pending, `.then/catch/finally` handlers wait for its outcome.
372-
373-
Sometimes, it might be that a promise is already settled when we add a handler to it.
374-
375-
In such case, these handlers just run immediately:
376-
>>>>>>> upstream/master
287+
````smart header="처리된 프라미스에도 핸들러를 등록할 수 있습니다"
288+
프라미스가 대기 상태라면 .then/catch/finally 핸들러는 결과를 기다립니다.
289+
핸들러를 등록할 때 프라미스가 이미 처리된 상태일 수도 있습니다.
290+
이런 경우 핸들러는 즉시 실행됩니다.
377291
378292
```js run
379293
// 아래 프라미스는 생성과 동시에 이행됩니다.
@@ -382,29 +296,18 @@ let promise = new Promise(resolve => resolve("완료!"));
382296
promise.then(alert); // 완료! (바로 출력됨)
383297
```
384298
385-
<<<<<<< HEAD
386-
가수와 팬, 구독리스트 시나리오보다 프라미스가 더 복잡하다고 말한 이유가 바로 이런 기능 때문입니다. 가수가 신곡을 발표한 이후에 구독 리스트에 이름을 올리는 팬은 신곡 발표 여부를 알 수 없습니다. 구독 리스트에 이름을 올리는 것이 선행되어야 새로운 소식을 받을 수 있기 때문이죠.
299+
가수와 팬, 구독리스트 시나리오보다 프라미스가 더 강력하게 만드는 이유가 바로 이런 기능 때문입니다. 가수가 신곡을 발표한 이후에 구독 리스트에 이름을 올리는 팬은 신곡 발표 여부를 알 수 없습니다. 구독 리스트에 이름을 올리는 것이 선행되어야 새로운 소식을 받을 수 있기 때문이죠.
387300
388301
그런데 프라미스는 핸들러를 언제든 추가할 수 있다는 점에서 구독리스트 시나리오보다 더 유연합니다. 결과가 나와 있는 상태에서도 핸들러를 등록하면 결과를 바로 받을 수 있습니다.
389302
````
390303

391-
이제 실제 동작하는 예시를 보며 프라미스로 어떻게 비동기 동작을 처리하는지 살펴봅시다.
392304

393305
## 예시: loadScript [#loadscript]
394306

395-
이전 챕터에서 스크립트 로딩에 사용되는 함수 `loadScript`를 작성해 보았습니다.
396-
=======
397-
Note that this makes promises more powerful than the real life "subscription list" scenario. If the singer has already released their song and then a person signs up on the subscription list, they probably won't receive that song. Subscriptions in real life must be done prior to the event.
398-
399-
Promises are more flexible. We can add handlers any time: if the result is already there, they just execute.
400-
````
401-
402-
## Example: loadScript [#loadscript]
307+
이제 실제 동작하는 예시를 보며 프라미스로 어떻게 비동기 동작을 처리하는지 살펴봅시다.
403308

404-
Next, let's see more practical examples of how promises can help us write asynchronous code.
309+
이전 챕터에서 스크립트 로딩에 사용되는 함수 `loadScript`를 작성해 보았습니다.
405310

406-
We've got the `loadScript` function for loading a script from the previous chapter.
407-
>>>>>>> upstream/master
408311

409312
복습 차원에서 콜백 기반으로 작성한 함수를 다시 살펴봅시다.
410313

0 commit comments

Comments
 (0)