POMOTODO : 이슈 (setInterval inactive issue)

2022. 1. 8. 12:30프로그래밍/개인프로젝트

POMOTODO를 만들면서 작성한 코드를 복습하기 위해 작성하는 글입니다.

 

 

POMOTODO.kr

 

 

What is POMOTODO?


1. 문제 인식


실제로 공부할 때 POMOTODO를 이용했는데 타이머를 25분 설정했지만 25분이 넘어가도 완료되지 않고 절반 정도만 진행되어 있는 문제 발생



2. 문제 원인 분석


타이머가 진행될 때마다 console.log를 출력하도록 하고 개발자 도구를 열어서 잘 작동하는지 검사

브라우저 외의 프로그램을 활성화하거나 브라우저의 다른 탭을 사용하면 작동이 점점 느려지는 문제를 발견했음

stackoverflow 검색 결과 브라우저가 비활성화 상태면 setTimeout이나 setInterval의 성능을 제한을 하기 때문에

 Background Thread에서 스크립트를 실행하기 위해서 webworker를 사용해야 한다는 정보 입수


3. 문제 해결

 

내 프로그램에서 setInterval을 사용하는 항목을 체크했고 그 항목들은 webworker를 사용해서 구현한다

 

- 포모도로 타이머포모도로 타이머의 애니메이션 두 가지 항목에서 setInterval을 사용하므로 worker 실행파일을 두가지로 만들어줬음

//webworker.js

let intervalID;

self.onmessage = function(e){
    if(typeof(e.data) == 'number'){
        let seconds = e.data;
        intervalID = setInterval(operateTimer, 1000);
        function operateTimer(){
            seconds--;
            postMessage(seconds);
            if(seconds == "0"){
                clearInterval(intervalID);
            }
        }
    }else if(e.data == 'stop'){
        clearInterval(intervalID);
        postMessage('stop worker method');
    }
}
//webworkerAnimation.js


let timeAnimation;
let t=100;
self.onmessage = function(e){
    if(typeof(e.data) == 'number'){
        // 애니메이션 관련
        timeAnimation = setInterval(draw, e.data);
        function draw(){
            if(t>0){
                t -= 0.1;
                postMessage(t);
            }else if(t < 0){
                clearInterval(timeAnimation)
                t=100;
            }
        }
    }else if(e.data == 'stop'){
        // console.log('스탑메소드');
        clearInterval(timeAnimation);
        t=100;
        postMessage('stop worker-animation method');
    }
}

- main.js에서 worker와 통신하는 코드 작성

* webworker와 관련 없는 코드는 삭제했음

//main.js
let worker = new Worker('worker.js');
let animationWorker = new Worker('workerAnimation.js');

// 타이머가 시작될 때 수행될 코드
function startRecodList(){ 
    worker.postMessage(pomodoroDelay);
    worker.onmessage = function(e){
        let workerMinutes;
        if(parseInt(e.data/60) > 9)
            workerMinutes = parseInt(e.data/60);
        else
            workerMinutes = "0"+parseInt(e.data/60);
        let workerSeconds;
        if(parseInt(e.data%60) > 9)
            workerSeconds = parseInt(e.data%60);
        else
            workerSeconds = "0"+parseInt(e.data%60);
        appendMinutes.textContent = workerMinutes;
        appendSeconds.textContent = workerSeconds;
        if(workerMinutes == '00'&&workerSeconds == '00'){
            stopRecordList();
        }
    }
    // 애니메이션 관련 웹 워커
    animationWorker.postMessage(pomodoroDelay);
    animationWorker.onmessage = function(e){
        color1(e.data ,pieChart);
    }
};
// 타이머가 정지될 때 수행될 코드
function stopRecordList(){ 
    worker.postMessage('stop');
    worker.onmessage = function(e){
    }
    animationWorker.postMessage('stop');
    animationWorker.onmessage = function(e){
        $(pieChart).css({
            "background":"#eef1f590"
        });
    }
}

타이머의 시간을 저장하는 변수인 pomodoroDelay를 postMessage의 파라미터로 워커에 전달해주도록 작성하고

워커에서는 받은 값을 사용하기 위해 onMessage를 통해 들어오는 인자e의 data인 e.data를 사용해서 매초 1씩 감소시켜서 리턴해준다

홈페이지에서는 매초 값을 받을 때마다 시간을 변경해주도록 코드를 작성해줌

 

- 참고 -

 

워커생성 (main.js에 작성)

var worker = new Worker(불러 올 JS파일 (ex. worker.js));

워커로 메시지 보내기 (main.js에 작성)

worker.postMessage(보낼 메시지);

main.js에서 워커가 보낸 메시지 받기 (main.js에 작성)

worker.onmessage = function() { ... }

워커에서 main.js로부터 온 메시지 받기 (worker.js에 작성)

self.onmessage = function(e){
	console.log(e.data) 
    // e.data == main.js에서 보낸 메시지
]