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을 사용을 햇다.