TIL
2024년 12월 9일 TIL
kagan-draca
2024. 12. 13. 18:05
JavaScript map() async 콜백 함수
Item Class
class Item {
...
async isItemUsable(item, user) {
// 스팀팩 사용 가능 여부 확인 해주는 조건문
if (this.items[item.itemId - BASE_ITEM_ID_OFFSET].itemId === STIMPACK_POTION_ID) {
// 스팀팩(광포화 포션)
return (
!user.stat.stimPack &&
this.items[item.itemId - BASE_ITEM_ID_OFFSET].count > 0 &&
user.stat.hp > 50
);
}
// 다른 아이템들은 개수가 0 이상이면, 사용 가능
return item.count > 0;
}
...
}
export default Item;
내부 async 메서드를 JavaScript의 아래와 같이 map 함수를 사용해
const buttons = items.map(async(item) => ({
msg: ${itemsName[item.itemId - BASE_ITEM_ID_OFFSET]}(보유 수량: ${item.count}),
enable: await this.user.inventory.isItemUsable(item, this.user),
}));
새로운 배열을 반환 받고자 시도할 경우
위와 같이 enable(key) 값에 Promise { false }(value)라는 값이 저장되는 문제가 존재했다.
이유로는 map의 콜백 함수를
async(item) => ({
enable: await this.user.inventory.isItemUsable(item, this.user)
});
async로 처리 할 경우, map 내부에서 각 호출 결과를 Promise로 처리하기 때문이었다.
이러한, 문제는 JavaScript 내장 함수를 비동기 처리할 때 동작 원리를
정확하게 이해하지 못 한 상황에서 발생한 오류였고, 이를 해결하기 위해서는
const buttons = await Promise.all(
items.map(async (item) => ({
msg: `${itemsName[item.itemId - BASE_ITEM_ID_OFFSET]}(보유 수량: ${item.count})`,
enable: await this.mover.inventory.isItemUsable(item, this.mover),
})),
);
buttons.push({ msg: BUTTON_BACK, enable: true });
위와 같이 await Promise.all()로 해당 코드를 감싸줄 경우 해결할 수 있었다.
Promise.all()로 해결된 이유는 모든 작업을 병렬로 처리해 모든 병렬 작업이 완료될 때까지
대기 및 완료된 후 결과를 반환해주기 때문이었다.
이러한, Promise.all()로 병렬처리를 수행할 경우, 이점은
순차적으로 처리하는 것 보다 속도가 훨씬 빨라지고, 하나라도 예외가 발생할 경우
reject로 오류를 일괄적으로 처리할 수 있다는 장점이 존재했다.