무단 전재를 금지합니다
1. 고가의 계산 처리
아마도 복잡한 Javascript 애플리케이션 개발에서 가장 복잡한 측면은 사용자 인터페이스의 단일 스레드 특성일 것입니다. Javascript가 사용자 상호 작용을 처리할 때 가장 좋은 상황은 느린 응답이고, 최악의 상황은 응답하지 않아 브라우저가 중단되는 것입니다(Javascript가 실행되면 페이지의 모든 업데이트 작업이 일시 중지됩니다). 이러한 사실로 인해 모든 복잡한 작업(100ms를 초과하는 모든 계산)을 관리 가능한 수준으로 줄이는 것이 필수적입니다. 또한 스크립트가 5초 이상 실행된 후에도 중지되지 않으면 일부 브라우저(예: Firefox 및 Opera)에서는 스크립트가 응답하지 않음을 사용자에게 경고하는 프롬프트 상자를 생성합니다.
이는 분명히 바람직하지 않으며 응답하지 않는 인터페이스를 생성하는 것은 좋지 않습니다. 그러나 이는 대량의 데이터를 처리해야 하는 경우(예: 수천 개의 DOM 요소 처리)에 해당됩니다.
이때 타이머가 특히 유용합니다. 타이머는 Javascript 코드의 실행을 효과적으로 일시 중지할 수 있기 때문에 브라우저가 실행 코드를 중단하는 것을 방지할 수도 있습니다(개별 코드가 브라우저를 중단시킬 만큼 충분하지 않은 경우). 이를 염두에 두고 일반적이고 집중적인 루프 계산을 비차단 계산에 통합할 수 있습니다. 이러한 유형의 계산이 필요한 다음 예를 살펴보겠습니다.
장기 실행 작업:
<테이블><tbody></tbody></table>
// 정상, 집중, 작동
var table = document.getElementsByTagName("tbody");
for ( var i = 0; i < 2000; i++ ) {
var tr = document.createElement("tr");
for(var t = 0; t < 6; t++ ){
var td = document.createElement("td");
td.appendChild(document.createTextNode("" + t));
tr.appendChild(td);
}
table.appendChild(tr);
}
}
이 예에서는 총 26,000개의 DOM 노드를 생성하고 숫자를 테이블에 채웁니다. 이는 비용이 너무 많이 들고 브라우저가 중단되고 정상적인 사용자 상호 작용이 방해될 가능성이 높습니다. 여기에 타이머를 도입하면 더 나은 결과를 얻을 수 있습니다.
타이머를 사용하여 장기 실행 작업을 분할합니다.
<테이블><tbody></tbody></table>
var table = document.getElementsByTagName("tbody");
var i = 0, 최대 = 1999;
setTimeout(함수(){
for ( var 단계 = i + 500; i < 단계; i++ ) {
var tr = document.createElement("tr");
for(var t = 0; t < 6; t++ ){
var td = document.createElement("td");
td.appendChild(document.createTextNode("" + t));
tr.appendChild(td);
}
}
table.appendChild(tr);
}
if (i < 최대 )
setTimeout(args.callee, 0);
}, 0);
수정된 예에서는 집중적인 계산을 네 부분으로 나누어 각각 6500개의 노드를 생성합니다. 이러한 계산은 브라우저의 정상적인 흐름을 방해할 가능성이 없습니다. 최악의 시나리오는 이러한 수치가 언제든지 조정될 수 있다는 것입니다(예를 들어 각 셀이 3500개의 DOM 노드를 생성하도록 수치를 250-500 사이로 변경). 하지만 가장 인상적인 것은 새로운 비동기 시스템에 적응하기 위해 코드를 변경한 방법입니다. 요소의 숫자가 올바르게 생성되었는지 확인하려면 더 많은 작업을 수행해야 합니다(루프가 영원히 끝나지 않음). 코드는 원래 코드와 매우 유사합니다. 코드 조각 간의 반복 상태를 유지하기 위해 클로저를 사용한다는 점에 유의하세요. 클로저가 없으면 이 코드는 의심할 여지 없이 더 복잡해집니다.
이 기술을 사용하면 원본과 비교하여 분명한 변화가 있습니다. 긴 브라우저 중단이 4개의 시각적 페이지 업데이트로 대체되었습니다. 브라우저는 이러한 코드 조각을 가능한 한 빨리 실행하려고 시도하지만 타이머의 각 단계 후에 DOM 변경(예: 대규모 업데이트)도 렌더링합니다. 대부분의 경우 사용자는 이러한 유형의 업데이트를 인식하지 못하지만 이러한 업데이트가 발생한다는 사실을 기억하는 것이 중요합니다.
이 기술이 나에게 특히 효과가 있을 수 있는 한 가지 상황이 있습니다. 바로 대학생의 일정을 계산하기 위해 만든 애플리케이션입니다. 처음에 응용 프로그램은 일반적인 CGI였습니다(클라이언트가 서버와 통신하고 서버가 일정을 계산하여 반환했습니다). 하지만 이를 변경하고 모든 일정 계산을 클라이언트에 넣었습니다. 일정 계산 보기는 다음과 같습니다.
이러한 계산은 상당히 비용이 많이 듭니다(정답을 찾으려면 수천 개의 순열을 탐색해야 합니다). 이 문제는 일정 계산을 실제 단위로 분할하여 해결됩니다(완성된 부분으로 사용자 인터페이스 업데이트). 결국 사용자는 빠르고 반응성이 뛰어나며 사용 가능한 사용자 인터페이스를 제공했습니다.
기술이 얼마나 유용한지 놀랄 때가 많습니다. 테스트 상자와 같은 장기 실행 프로그램에서 자주 사용되는 것을 발견하게 될 것입니다(이 장의 마지막 부분에서 이에 대해 논의합니다). 더 중요한 것은 이 기술이 사용자에게 풍부한 경험을 제공하는 동시에 브라우저 환경의 한계를 해결하는 것이 얼마나 쉬운지를 보여 준다는 것입니다.