배열 함수는 겁나게 많다. (feat. 비동기 순차실행)

jh_leitmotif·2022년 3월 1일
0

Frontend 개인 공부

목록 보기
21/24
post-thumbnail

개요

자바스크립트의 Array에는 함수가 정말 많다. 아니? 디이이이지게 많다.

참고 링크 : https://www.w3schools.com/jsref/jsref_obj_array.asp

왠만한건 알아서 쓰지만 가끔 사용법이 기억이 안나면 RunJS에 치곤 하는데요,

그 중에서도 특이한 친구들이 있습니다.

Array.reduce
Array.map    Array.forEach
Array.filter 
Array.every  Array.some
Array.find   Array.findIndex

그래서 이 함수들은 뭔디?

인자로 currentValue(또는 element), index, array를 공통적으로 가진다.

예제를 들어보겠습니다.

언급한 모든 함수들은 세 개의 인자를 공통적으로 가집니다.

currentValue : 현재 순회 중인 아이템의 값
index : 현재 순회 중인 아이템의 인덱스
array : 해당 함수를 호출한 원본 배열

Array.map vs Array.forEach

간단하게 설명해서, map은 배열을 반환하고 forEach는 그렇지 않습니다.

두 함수 모두 콜백을 실행합니다만, 배열을 반환하느냐? 하지 않느냐? 에 대한 차이입니다.

주의할 것은 원본 배열을 수정하는 것이 아니라는 점인 것 같습니다.

사용 예)
forEach의 경우
 - 반복적인 작업이 있고, 그것을 간단히 표현하고 싶을 때. 
map의 경우
 - React에서 동일한 컴포넌트를 반복적으로 그릴 때.
 - 원본 배열을 통해 새로운 배열을 만들어야할 때.

Every vs Some

쉽게 말해서 and와 or의 차이입니다.

and는 모든 조건이 true일 때만 true지만 or은 무언가가 true면 true인 것과 같습니다.

사용 예)
every의 경우
 - 로그인시 ID, 비밀번호 input이 모두 채워졌는지.
some의 경우
 - 평가 항목 중 단 하나라도 낙제점이 있는지.

Find vs FindIndex

find는 값을 반환하고, findIndex는 해당 값의 인덱스를 반환합니다.


reduce는 조금 특별하다.

앞서 언급한 함수들과 다르게 reduce는 콜백에 'accumulator'라는 인자를 하나 더 받습니다.

이는 이전에 실행된 콜백의 반환값을 의미하고, 또 누적한 값이라고도 할 수 있습니다.

그리고 2번째 인자는 accumulator의 최초 값을 의미하며 미 정의시 호출된 배열의 첫 번째 요소로 설정됩니다.

가장 간단히 배열의 모든 요소를 더한 값을 구한다고 할 때, for 대신 reduce를 이용하면 조금은 코드의 단순화를 꾀할 수 있습니다.

비동기 동작들을 순차로 실행시켜보자.

'누적한 값을 인자로 받는다' 라는 특성을 다르게 해석하면

이전 loop의 값을 가져온다

라고 볼 수 있습니다.

즉, reduce는 async/await를 이용해 비동기 동작을 순차실행시킬 수 있습니다.

const API_LIST=[...]

async function apiSynchronize() {
	await API_LIST.reduce(async (promise,url)=>{
    	let promiseResult = await promise;
        promiseResult = await doAxios({url:url})
        return promiseResult;
    },{})
}

또는 Promise chaining을 사용할 수 있습니다.

const API_LIST=[...]

async function apiSynchronize() {
	await API_LIST.reduce((promise,url)=>{
    	return promise.then(()=>{
        	doAxios({url:url})
        })
    },Promise.resolve())
}

덧붙여 클래식하게, for문도 사용할 수 있긴 합니다.

const API_LIST=[...]

async function apiSynchronize(){
	for (const apis of API_LIST){
    	await doAxios({url:apis});
    }
}

순차실행된 결과 vs 비동기 실행된 결과

기준이 되는 api는 위와 같습니다.

친숙한 dog api를 사용했습니다.

api가 선언된 순서와 다르게 나옵니다.

반면, 이 경우 선언된 순서에 맞게 나옵니다.

순차실행의 장점은 모든 비동기 동작이 완료되어야 그 다음 동작을 발생시킬 수 있다는 점에 있습니다. 로딩 중인지? 모두 로딩 되었는지? 에 대한 것들을 제어하기 쉽습니다.

비동기 실행의 장점은 동작이 병렬적으로 수행되기에 완료 시점이 빠릅니다. 다만 로딩 상태에 대해서는 별도의 처리가 필요합니다.

그래서 넌 이걸 왜 했는데?

모든 데이터를 받은 뒤, 전부 완료되면 컨텐츠를 렌더링하는 것의 구현이 필요했습니다.

1. 응답이 발생하면 .then() 체이닝으로 몇 개의 통신이 완료되었는지 처리
2. reduce 자체에 .then() 체이닝으로 로딩 완료 또는 에러 발생 처리
3. 로딩 중일 때 검색 버튼을 누르면 alert 표시
4. 로딩 완료시 컨텐츠 렌더링

profile
Define the undefined.

0개의 댓글