Skip to content

Commit fd1fb52

Browse files
authored
docs: 16장 정리
1 parent bae7e1c commit fd1fb52

File tree

1 file changed

+222
-0
lines changed
  • 김서현/16. 타임라인 사이에 자원 공유하기

1 file changed

+222
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# 16. 타임라인 사이에 자원 공유하기
2+
3+
- [큐를 사용해 DOM이 업데이트되는 순서 보장하기](#큐를-사용해-dom이-업데이트되는-순서-보장하기)
4+
- [큐를 재사용할 수 있도록 만들기](#큐를-재사용할-수-있도록-만들기)
5+
- [큐를 건너뛰도록 만들기](#큐를-건너뛰도록-만들기)
6+
7+
---
8+
9+
### 좋은 타임라인의 원칙
10+
11+
1. 타임라인은 적을수록 이해하기 쉬움
12+
2. 타임라인은 짧을수록 이해하기 쉬움
13+
3. 공유하는 자원이 적을 수록 이해하기 쉬움
14+
4. 자원을 공유한다면 서로 조율해야 함 - 올바른 결과를 주지 않는 실행 순서를 없앰
15+
- 16장에서는 타임라인끼리 공유하는 자원 조율 위해 재사용 가능한 방법 만들 것
16+
5. 시간을 일급으로 다룸
17+
18+
---
19+
20+
## 큐를 사용해 DOM이 업데이트되는 순서 보장하기
21+
22+
1. 장바구니에 존재하는 버그 - DOM 자원을 공유해서 두 타임라인 사이에 실행 순서가 중요
23+
- 첫 번째 클릭, 두 번째 클릭 타임라인 - 왼쪽 다음 오른쪽이 기대한 결과이지만 오른쪽 다음 왼쪽 케이스도 생길 수 있음.
24+
2. DOM이 업데이트되는 순서를 보장해야
25+
- 오른쪽 먼저 실행되는 것 막아야 하나 DOM 업데이트는 통제 불가능함
26+
- → 큐 사용
27+
3. 자바스크립트에서 큐 만들기
28+
- 큐는 자료구조이나, 타임라인 조율에 사용한다면 `동시성 기본형`(자원을 안전하게 공유할 수 있는 재사용 가능한 코드)이라 부름.
29+
- JS에는 큐 자료구조가 없어서 만들어야 함
30+
4. 큐에서 처리할 작업을 분리 - 동시에 실행되는 것 막기
31+
32+
```tsx
33+
function add_item_to_cart(item) {
34+
cart = add_item(cart, item);
35+
// calc_cart_total(cart, update_total_dom);
36+
37+
// 1. 큐에서 처리할 작업을 큐에 넣기
38+
// 클릭 핸들러에서 큐에 항목 추가
39+
update_total_queue(cart);
40+
}
41+
42+
// 기존 코드
43+
function calc_cart_total(cart, callback) {
44+
var total = 0;
45+
cost_ajax(cart, function (cost) {
46+
total += cost;
47+
shipping_ajax(cart, function (shipping) {
48+
total += shipping;
49+
callback(total);
50+
});
51+
});
52+
}
53+
54+
// 6. 변수와 함수를 함수 범위로 넣기
55+
// 작업한 모든 코드를 Queue() 함수 내부에 넣어서 전역변수를 Queue()의 지역변수로 만듦
56+
function Queue() {
57+
var queue_items = [];
58+
// 3. 두 번째 타임라인이 첫 번째 타임라인과 동시에 실행되는 것 막기
59+
// 현재 동작하고 있는 다른 작업이 있는지 확인
60+
var working = false;
61+
62+
function runNext() {
63+
// 3. 두 번째 타임라인이 첫 번째 타임라인과 동시에 실행되는 것 막기
64+
// 동시에 타임라인 두 개가 동작하는 것을 막음
65+
if (working) return;
66+
// 5. 항목이 없을 때 멈추게 하기
67+
// 큐가 비어있으면 멈춤
68+
if (queue_items.length === 0) return;
69+
working = true;
70+
71+
// 2. 큐에 있는 첫 번째 항목 실행
72+
// 배열의 첫 번째 항목을 꺼내 카트에 넣음
73+
var cart = queue_items.shift();
74+
calc_cart_total(cart, function (total) {
75+
// 4. 다음 작업을 시작할 수 있도록 콜백 함수 고치기
76+
// 작업 완료 표시하고 다음 작업 시작
77+
update_total_dom(total);
78+
working = false;
79+
runNext();
80+
});
81+
}
82+
83+
// 6. 변수와 함수를 함수 범위로 넣기
84+
// update_total_queue로 쓸 함수 리턴
85+
return function (cart) {
86+
// 1. 큐에서 처리할 작업을 큐에 넣기
87+
// 배열 끝에 항목 추가
88+
queue_items.push(cart);
89+
90+
// 2. 큐에 있는 첫 번째 항목 실행
91+
// 큐에 항목 추가하고 워커 시작
92+
setTimeout(runNext, 0);
93+
};
94+
}
95+
96+
var update_total_queue = Queue();
97+
```
98+
99+
---
100+
101+
## 큐를 재사용할 수 있도록 만들기
102+
103+
```tsx
104+
// 2. 워커 행동을 바꿀 수 있도록 밖으로 뺌 - 인자 추가
105+
// function Queue() {
106+
function Queue(worker) {
107+
var queue_items = [];
108+
var working = false;
109+
110+
function runNext() {
111+
if (working) return;
112+
if (queue_items.length === 0) return;
113+
working = true;
114+
115+
// var cart = queue_items.shift();
116+
var item = queue_items.shift();
117+
118+
// 1. done() 함수 빼내기
119+
// 2. 워커 행동을 바꿀 수 있도록 밖으로 뺌
120+
// calc_cart_total(cart, function (total) {
121+
// update_total_dom(total);
122+
// working = false;
123+
// runNext();
124+
// });
125+
126+
// 3. 작업이 끝났을 때 실행하는 콜백을 받기
127+
// worker(cart, function () {
128+
worker(item.data, function (val) {
129+
working = false;
130+
// 4. 작업이 완료됐을 때 콜백 부르기
131+
// item.callback을 비동기로 부름
132+
setTimeout(item.callback, 0, val);
133+
runNext();
134+
});
135+
}
136+
137+
// 3. 작업이 끝났을 때 실행하는 콜백을 받기
138+
// return function(cart) {
139+
// queue_items.push(cart);
140+
return function (data, callback) {
141+
queue_items.push({
142+
// 배열에 데이터와 콜백 모두 넣음
143+
data: data,
144+
callback: callback || function () {},
145+
});
146+
setTimeout(runNext, 0);
147+
};
148+
}
149+
150+
// 1. done() 함수 빼내기
151+
// calc_cart_worker()의 콜백함수를 done()이라 이름짓고 빼냄
152+
// 큐에서 하는 일(calc_cart_total() 부르기)과
153+
// 큐를 반복해 처리하는 코드(runNext()를 부르는 코드) 분리
154+
// 2. 워커 행동을 바꿀 수 있도록 밖으로 뺌
155+
// 일반적인 큐 만들기 위해 특정 도메인에 한정적인 기능 분리
156+
// Queue 함수의 인자로 넘겨 사용
157+
// 특정 도메인에 한정됨 - 구체적 인자명 사용
158+
function calc_cart_worker(cart, done) {
159+
calc_cart_total(cart, function (total) {
160+
update_total_dom(total);
161+
done(total);
162+
});
163+
}
164+
165+
var update_total_queue = Queue(calc_cart_worker);
166+
```
167+
168+
- Queue()
169+
- 액션에 새로운 능력을 줄 수 있는 고차함수
170+
- 액션에 순서를 보장해줌
171+
- 동시성 기본형(자원을 안전하게 공유할 수 있는 재사용 가능한 코드)
172+
173+
---
174+
175+
## 큐를 건너뛰도록 만들기
176+
177+
- 기존 큐: 작업이 끝나야 다음 작업 시작됨 → 연속 요청 들어올 경우 느림
178+
- 드로핑 큐: 새로운 작업이 들어오면 건너뛸 수 있음
179+
180+
```tsx
181+
// function Queue(worker) {
182+
// max: 보관할 수 있는 최대 큐 크기 넘김
183+
function DroppingQueue(max, worker) {
184+
var queue_items = [];
185+
var working = false;
186+
187+
function runNext() {
188+
if (working) return;
189+
if (queue_items.length === 0) return;
190+
working = true;
191+
var item = queue_items.shift();
192+
worker(item.data, function (val) {
193+
working = false;
194+
setTimeout(item.callback, 0, val);
195+
runNext();
196+
});
197+
}
198+
199+
return function (data, callback) {
200+
queue_items.push({
201+
data: data,
202+
callback: callback || function () {},
203+
});
204+
// 큐에 추가한 후에 항목이 max 넘으면 모두 버림
205+
while (queue_items.length > max) {
206+
queue_items.shift();
207+
}
208+
setTimeout(runNext, 0);
209+
};
210+
}
211+
212+
function calc_cart_worker(cart, done) {
213+
calc_cart_total(cart, function (total) {
214+
update_total_dom(total);
215+
done(total);
216+
});
217+
}
218+
219+
// var update_total_queue = Queue(calc_cart_worker);
220+
// 한 개 이상은 모두 버림
221+
var update_total_queue = DroppingQueue(1, calc_cart_worker);
222+
```

0 commit comments

Comments
 (0)