[TIL] typing 효과2

이진호·2023년 10월 13일
0

TIL

목록 보기
5/66

이전글

https://velog.io/@dygmm4288/TIL-typing-%ED%9A%A8%EA%B3%BC

typing 효과에 대해서 어떻게 해야 더 잘 조작할 수 있을까라는 고민을 하게 됐고 비동기 동작에 대해서 다시 한번 생각을 해봤다.

우선, 글자 typing 효과는 다음과 같은 3가지의 큰 작업이 필요하다
1. text를 하나씩 채워 넣는다
2. 잠시 기다린다
3. 채워넣은 text를 하나씩 지운다

각 작업은 하나의 프로세스로 3번까지 모두 완료가 된다면 다시 1번으로 넘어가야 한다.

이걸 기존에는 setInterval 함수를 통해서 조작을 했었는데 그럴 필요 없이 async/await을 활용하면 끝날때까지 기다렸다가 다시 실행을 하면 되겠다고 생각해서 다음과 같이 구현했다.

// typing 포로세스
async function typing(element,speed = 100,delay = 1000) {
	if(!element || !element instanceof HTMLElement) return;
    
	await moveForward(speed,delay)(element)(texts[curIndex++]);
    
    curIndex %= texts.length;
    await moveBack(speed)(element);
    return;
}

async function infinite() {
	while(true) {
    	await typing(secondText);
        // secondText는 html element
    }
}

정상적으로 동작하는 것을 확인했고, moveBack 이후에 조금 기다려주면 좋을 것 같아서 다음과 같이 수정을 했다.

function moveBack(speed,option) {
	return async element => {
    	while(element.innerText) {
        	element.innerText = element.innerText.slice(0,-1);
            await wait(speed);
        }
        if(option.backWait) await wait(option.backWait);
	}
}

moveBack에 옵션을 준 만큼 다른 함수들에도 옵션을 줘서 나머지 코드들은 다음과 같다.

최종 코드

const secondText = select('.second-text');

function wait(time) {
  return new Promise((res) =>
    setTimeout(() => {
      res();
    }, time),
  );
}

function moveForward(speed, delay) {
  return (element) => async (text) => {
    let textIndex = 0;
    const size = text.length;
    while (textIndex < size) {
      element.innerText += text[textIndex++];
      await wait(speed);
    }
    await wait(delay);
  };
}
function moveBack(speed, option) {
  return async (element) => {
    while (element.innerText) {
      element.innerText = element.innerText.slice(0, -1);
      await wait(speed);
    }
    if (option.backWait) await wait(option.backWait);
  };
}
const texts = ['개발자', '꿈나무', '칠칠맞조'];
let curIndex = 0;
async function typing(element, option) {
  if (!element || !element instanceof HTMLElement) return;
  const { speed = 100, delay = 1000, backWait } = option || {};
  await moveForward(speed, delay)(element)(texts[curIndex++]);
  curIndex %= texts.length;
  await moveBack(speed, { backWait })(element);
  return true;
}
async function infinite() {
  while (true) {
    await typing(secondText, { backWait: 500 });
  }
}
infinite();

function select(selector) {
  return document.querySelector(selector);
}

느낀점

비동기 작업들은 순서가 정해져있지 않다. 이러한 비동기 작업들을 가끔은 순서가 매우 중요해지는 순간들이 오는데 이를 컨트롤 할 수 있게 하는 여러 방식들이 있다.
Promise, async / await, generator가 있는데 각각 필요에 따라 쓰면 충분히 좋은 도구들이라 필요에 따라서 사용하면 좋을 것 같다.
내가 Promise와 generator를 사용하지 않은 이유는..

  • generator는 익숙치 않은 문법이라 사용을 못한 것도 있지만 한번 큰 흐름이 끝나고 나서는 다시 반복을 해야하는데 그때마다 next를 호출해야하는건지 한번만 호출하니까 한번의 동작을 완료된 이후로 동작을 안했다.

  • Promise는 Promise를 이용하여 각 작업을 세부적으로 하나하나 나눌 수 있엇는데 막상 그렇게 작성하니 가독성 측면에서 많이 부족했던 것 같다.

  • async/await 을 사용하니 비동기적인 작업들이 하나의 동기적인 작업들로 보여지고 좀 더 직관적으로 코드를 볼 수 있어서 async/await을 사용을 햇다.

profile
dygmm4288

0개의 댓글