TIL

0l0l·2021년 6월 18일
0

TIL

목록 보기
49/86

반응 속도 테스트 (비동기 코드 학습)
;특정 화면이 뜰 때의 시각과 사용자가 화면을 보고 클릭한 시각의 차이
시간 관련 메서드를 제공하는 Date 객체 사용

<반응속도 측정 과정 설명>
(파랑 화면: 대기(wait), 빨강 화면: 준비(ready), 초록 화면: 클릭(run))
《처음》파랑 화면 → 화면 한 번 클릭 → 빨강 화면으로 전환 → 랜덤으로 임의의 시간흐름 → 초록 화면으로 '자동' 전환《측정 시작》 → (보자마자)화면 클릭《측정 종료》 → 반응 속도 측정 결과 표시

타이머는 비동기이기 때문에 대기하고 있다가 타이머가 시작할 때 시간초를 계산한다.
※ 타이머도 이벤트 리스너와 마찬가지로 '비동기'로 동작하므로 순서도에서 분리하여 그린다. (코드 순서 흐름대로 동작하지 않으므로 대기가 필요하다.)

1. 클릭할 때 화면 전환하기

하나의 화면에 이벤트 리스너를 달아 클릭할 때마다 화면별로 다르게 동작하도록 구현한다.
현재 화면이 어떤 화면인지 알기 위해 각각의 클래스를 붙인다.
class는 여러 태그들을 동시에 선택하고 싶을 때도 사용하지만(html에서의 클래스),
자바스크립트 상에서 태그에 특정한 역할이 부여되었음을 알려줄 때 사용한다(js에서의 클래스).

< html 태그에 붙인 클래스 불러오는 방법>

태그.className; // 클래스

<태그에 해당 클래스가 들어있는지 확인하는 방법>

태그.classList.contains('클래스'); // true 또는 false로 반환

태그.classList.add('클래스'); // 클래스 추가
태그.classList.replace('기존클래스', '수정클래스'); // 클래스 수정
태그.classList.remove('클래스'); // 클래스 삭제

🔆이해 필요! 헷갈리지 않기!😵
화면 전환 순서 상, '파랑 → 빨강 → 초록' 화면이지만 초록 화면은 파랑 화면을 클릭하고 (바로 빨강 화면이 표시된 채) 타이머가 실행되어 랜덤 시간 이후에 나타난다. (빨강 화면 클릭 후 나타나는 것이 아님!)
∴ ('클릭' 이벤트가 실행되고) 초록 화면으로 전환되는 setTimeout 함수는 파랑 화면일 때의 조건 실행문에 작성해야 한다.

<랜덤 시간 설정하기(2초~3초 사이 = 2000ms~3000ms)>
0 ≤ Math.random() < 1
0 ≤ Math.random() × 1000 < 1000
2000 ≤ Math.floor(Math.random() * 1000) + 2000 < 3000

또는(내 생각)
0 ≤ Math.random() < 1
2 ≤ Math.random() + 2 < 3
2000 ≤ Math.floor((Math.random() + 2) * 1000) < 3000

2. 반응 속도 측정하기

시간 측정 시작(파랑 화면에서 클릭하여 초록 화면으로 전환 시)
시간 측정 종료(초록 화면 클릭 시)

<현재 시각, 과거 시각 측정하기>
Date 객체는 new 라는 예약어와 한 세트이다. 문자열이 아니라 객체이다.
직접 지정할 때 Date의 인수로 '연(FullYear), 월(Month), 일(Date), 시(Hours), 분(Minutes), 초(Seconds)'를 넣을 수 있으며, 월은 (문자열을 배열 안에서 꺼내는 방식으로) 숫자 0부터 시작한다. (1월 = January)

현재 시각에 가까울수록 숫자가 크다. (자바스크립트는 1970년 이후의 시간을 센다.)
현재 시간에서 과거 시간을 빼기 위해 시간을 기록·저장하려면 각각의 변수를 만들어야 한다.
시각 차이는 밀리초 단위로 표시되며 (÷ 1000)초, (➕ ÷60)분, (➕ ÷60)시, (➕ ÷24)일로 계산할 수 있다.

new Date(); // 현재 시각
new Date(2021, 5, 17); // 과거 시각(직접 지정)

(new Date(2021, 9, 11) - new Date(2021, 5, 18)) / (1000*60*60*24); // 115 (6월18일 기준 내 생일 며칠 남았나)

new Date.getFullYear() // 2021
new Date.getMonth() // 5 (= 6월)
new Date.getDate() // 19
let when = new Date.setDate(18) // 변수에 날짜 설정

✨헷갈리는 변수 선언 위치 이해하기!🤦‍♀️✨

  1. let블록 스코프이기 때문에 먼저 맨 위에 변수 선언하지 않고, 필요한 코드 부분에 let으로 변수 선언한다면 코드가 속한 블록 바깥에서는 변수를 접근하지 못해 에러가 발생한다.

  2. 함수는 한 번 실행되고 실행이 끝나면 함수 안에 있는 변수들이 다 날아가버리기(값이 리셋) 때문에 이후에 다른 조건일 때 실행이 불가하다. (참고: 아래 if문은 순차적으로 진행되는 조건문으로 모든 코드가 실행된다.)

∴ let이 블록 스코프이지만 함수 안에 변수 선언을 하면 위와 같은 문제가 발생하므로 함수 바깥에 선언해 전역 스코프(선언 이후 코드만 실행)가 되어야 한다.
(cf. var는 선언 이전의 코드도 실행 가능한 이상한X🥴)

let startTime; // ★변수 선언 위치
let endTime; // ★변수 선언 위치
$screen.addEventListener('click', (event) => {
  if (event.target.classList.contains('wait')) { // 파랑 화면
    $screen.classList.remove('wait');
    $screen.classList.add('ready');
    setTimeout(function () { // 파랑 화면 클릭 랜덤 시간 이후 초록 화면 전환
      startTime = new Date(); // 시간측정 시작
      $screen.classList.remove('ready');
      $screen.classList.add('run');
    }, Math.floor(Math.random() * 1000)) + 2000); // 2~3초 사이 랜덤
  } else if (event.target.classList.contains('ready') { // 빨강 화면
    ...
  } else if (event.target.classList.contains('run') { // 초록 화면
    endTime = new Date(); // 시간측정 종료
    $result.textContent = `${endTime - startTime}ms`; // 반응 시간 계산
    $screen.classList.remove('run');
    $screen.classList.add('wait');
  }
});

startTime은 addEventListener 바깥에 선언해야 한다.
각각의 조건은 다른 click으로 첫번째 클릭할 때 startTime을 측정하고, 두번째 클릭할 때 endTime을 측정한다.
즉, startTime을 addEventListener 안에 선언하면 endTime을 측정할 때 startTime이 다시 선언되어 저장된 값이 사라진다.

3. 평균 반응 속도 구하기

전체 갯수를 알지 못하는 반응 속도들을 기록해 두기 위해 배열을 만든다.
(일일이 구분하기 위해 변수 이름을 넣어 객체 리터럴로 만들 필요는 없다.)

✨ 배열에 요소들 평균 구하는 코드 외우기!★
reduce : 배열의 요소 각각 실행문을 반복해 배열의 값들을 하나의 새로운 값으로 합치는 메서드(★배열 만능 메서드)
배열을 객체 리터럴로 만들 수 있고, forEach, map, find, index, includes, indexOf 등의 배열 메서드를 reduce로 구현할 수 있다.
(map, reduce 배열 필수 메서드!)

const records = [];
const average = records.reduce((a, c) => { return a + c }) / records.length;

<초기값을 따로 설정하지 않은 경우>
초기값이 없다면 첫번째 요소가 초기값이 된다. 초기값은 첫번째 누적값으로 들어간다.
첫번째 요소를 제외하고 두번재 요소부터 reduce를 적용해 실행문(return문)이 반복된다. 반환값이 다음 번의 누적값이 된다.

<초기값을 설정한 경우>
별도로 설정한 초기값이 0인 경우 첫번째 누적값이 되고, 배열의 첫번째 요소가 현재값이 된다. 반환값이 다음 번의 누적값이 된다.

새로운 누적값이 undefined 되지 않도록 return 예약어를 반드시 작성해야 한다!
(중괄호와 return 예약어 생략 가능한 경우도 포함)

배열.reduce((누적값, 현재값) => {
  return 새로운 누적값;
}, 초기값);
// array.reduce((누적값, 현재값) => (누적값 + 현재값)[, 초기값]);

[1, 2, 3, 4].reduce((a, c) => a + c)); // 초기값 설정X, 초기값 1
[1, 2, 3, 4].reduce((a, c) => {
  return a + c;
}, 0); // 초기값 설정, 초기값 0

4. 성급한 클릭 막기

초록 화면이 될 때까지 기다리지 못하고 빨간 화면일 때 클릭하면 경고 메세지를 표시한다. clearTimeout을 이용해 초록 화면으로 전환될 때의 타이머를 멈추고 파랑 화면(대기)으로 넘어간다.

profile
천방지축 빙글빙글

0개의 댓글