Right now do !

Web worker를 이용한 javascript 비동기 호출

by 지금당장해

Web worker라는 개념은 javascript에서 비동기 Call을 처리하기 위해 준비된 객체이다. 물론 아주 오래된 브라우저는 않될것이다. 그런것은 각자 궁금하면 찾아보시고, 필자는 요즘 바쁘다. 간략하게 기록을 하고 글쓰기를 빠져나갈 생각이다.

 

시나리오

jsp에서 버튼을 하나두고 해당 버튼의 이벤트 처리 함수에서 Worker를 여러개 생성한다. 이 Worker를 통해 특정 js를 실행 하고 이 js에서는 원격 호출을 한다. Response가 오면 이를 호출자에게 Callback한다. Callback을 받은 jsp(서버사이드 스크립트가 아님, jsp상의 javascript)는 이를 화면에 나타낸다.

 

JSP소스

핵심은 new Worker이다. 인자로 경로가 있는데 이는 비동기 호출대상이 되는 javascript파일의 경로이다. woker.addEventListener는 javascript의 처리완료후 Callback을 받을 EndPoint이다. 이때 인자 e를 통해 함수의 결과 값을 받을 수 있다. 아래 소스에서는 버튼 한번 클릭에 3개의 worker가 생성되어 같은 js를 호출하도록 구성하였다. (특정 테스트 때문인데 그 자세한 설명은 넘어간다.) 이 Callback은 e를 통해 받은 결과를 html의 특정 위치에 attach하는 역할을 한다. 그리고 종료한다. (worker.terminate();) 실제 각 worker를 실행시키는 역할을 worker.postMessage(인자);가 수행한다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<html>
<body>
<h2>세션변수 동시 접근 증가 연산시 같은값 출력 할 수 있는 경우 POC</h2>
<div id="result"></div>
<button id="btn">run</button>
<script>
    document.querySelector('#btn').addEventListener('click', function () {

        var worker = new Worker('./worker.js');
        worker.addEventListener('message', function(e) {
            var div = document.createElement('div');
            div.textContent = e.data;
            document.querySelector('#result').appendChild(div);
            worker.terminate();
        });
        worker.postMessage('Start Worker 1');

        var worker2 = new Worker('./worker.js');
        worker2.addEventListener('message', function(e) {
            var div = document.createElement('div');
            div.textContent = e.data;
            document.querySelector('#result').appendChild(div);
            worker2.terminate();
        });
        worker2.postMessage('Start Worker 2');

        var worker3 = new Worker('./worker.js');
        worker3.addEventListener('message', function(e) {
            var div = document.createElement('div');
            div.textContent = e.data;
            document.querySelector('#result').appendChild(div);
            worker3.terminate();
        });
        worker3.postMessage('Start Worker 3');

        var div1 = document.createElement('div');
        div1.textContent = '------------------------------------------------';
        document.querySelector('#result').appendChild(div1);

    });
</script>
<%
    // 'AccessCnt' 세션 변수 1로 설청
    session.setAttribute("AccessCnt", 1);
%>
</body>
</html>

JS소스

다음은 worker에 의해 수행되는 JS의 소스이다. JSP소스에서 이 js는 worker.js로 저장 되었음을 알수 있었다.

var handleRequest = function(data) {
    postMessage(data); // Callback
};

self.addEventListener('message', function(e) {

    var xhr = new XMLHttpRequest();
    xhr.open('POST', './SessionIncr', true);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.onreadystatechange = function(e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
            handleRequest(xhr.responseText)
        }
    };

    xhr.send('param1=' + e.data);

});

self.addEventListener에 Worker의 postMessage를 통해 인자가 전달된다. 이를 이용하여 이런 저런 처리를 하고 CallBack point로 돌아가면 된다. (필자는 어떤 목적으로 원격 서블릿 호출을 했을 뿐이다.) 

 

실행 결과

비동기 호출이므로 각 worker의 결과수신의 순서를 보장 할 수 없다.

 

JSP실행 결과

블로그의 정보

지금 당장 해!!!

지금당장해

활동하기