# Chapter16. 타임라인 사이에 자원 공유하기
# 1. 자바스크립트에서 큐 만들기
# (1) 용어 정리
- 큐(Queue)
- 넣은 순서대로 항목을 꺼낼 수 있는 데이터 구조
- 동시성 기본형(Concurrency Primitive)
- 자원을 안전하게 공유할 수 있는 재사용 가능한 코드
- 동시성 기본형은 방법은 다르지만 모두 실행 가능한 순서를 제한하면서 동작한다.
- 기대하지 않는 실행 순서를 없애면 코드가 기대한 순서로 동작한다는 것을 보장할 수 있다.
# (2) 예시
function add_item_to_cart(item) {
cart = add_item(cart, item);
update_total_queue(cart);
}
function calc_cart_total(cart, callback) {
var total = 0;
cost_ajax(cart, function(cost) {
total += cost;
shipping_ajax(cart, function(shipping) {
total += shipping;
callback(total);
});
});
}
function Queue() {
var queue_items = [];
var working = false;
function runNext() {
if (working) return;
if (queue_items.length === 0) return;
working = true;
var cart = queue_items.shift();
calc_cart_total(cart, function(total) {
update_total_dom(total);
working = false;
runNext();
});
}
return function(cart) {
queue_items.push(cart);
setTimeout(runNext, 0);
}
}
var update_total_queue = Queue();
# 2. 큐를 재사용할 수 있도록 만들기
- 동시성 기본형은 액션을 고차 함수로 받는다. 이 고차 함수는 액션에 '순서 보장'이라는 슈퍼 파워를 준다.
function Queue(worker) {
var queue_items = [];
var working = false;
function runNext() {
if (working) return;
if (queue_items.length === 0) return;
working = true;
var item = queue_items.shift();
worker(item.data, function(val) {
working = false;
setTimeout(item.callback, 0, val);
runNext();
});
}
return function(data, callback) {
queue_items.push({
data: data,
callback: callback || function() {}
});
setTimeout(runNext, 0);
};
}
function calc_cart_worker(cart, done) {
calc_cart_total(cart, function(total) {
update_total_dom(total);
done(total);
});
}
var update_total_queue = Queue(calc_cart_worker);
# 3. 큐를 건너뛰도록 만들기
function DroppingQueue(max, worker) {
var queue_items = [];
var working = false;
function runNext() {
if (working) return;
if (queue_items.length === 0) return;
working = true;
var item = queue_items.shift();
worker(item.data, function(val) {
working = false;
setTimeout(item.callback, 0, val);
runNext();
});
}
return function(data, callback) {
queue_items.push({
data: data,
callback: callback || function() {}
});
while (queue_items.length > max) {
queue_items.shift();
}
setTimeout(runNext, 0);
};
}
function calc_cart_worker(cart, done) {
calc_cart_total(cart, function(total) {
update_total_dom(total);
done(total);
});
}
var update_total_queue = DroppingQueue(1, calc_cart_worker);