스택큐힙리스트

사용하기 : async/await 및 forEach 루프 본문

카테고리 없음

사용하기 : async/await 및 forEach 루프

스택큐힙리스트 2024. 1. 26. 15:44
반응형

forEach

루프에서 async/await를 사용하는 것에 문제가 있을까요? 파일 배열을 순회하고 각 파일의 내용에서 await를 시도하고 있습니다.
import fs from 'fs-promise'
async function printFiles () {
const files = await getFilePaths() // 이 코드는 잘 작동한다고 가정합니다.
files.forEach(async (file) => {
const contents = await fs.readFile(file, 'utf8')
console.log(contents)
})
}
printFiles()

이 코드는 작동하지만, 이 부분에서 문제가 발생할 수 있을까요? 다른 사람이 이러한 고차 함수에서 async/await를 사용하지 말아야 한다고 말했기 때문에 이 부분에 문제가 있는지 여쭙고 싶습니다.

답변 1

코드는 분명히 작동하지만, 예상한 대로 작동하지 않을 것으로 생각합니다. 그것은 여러 비동기 호출을 시작하지만, printFiles 함수는 즉시 반환됩니다.


순차적으로 읽기


파일을 순차적으로 읽으려면, forEach를 사용할 수 없습니다. 대신에 modern한 for ... of 루프를 사용하고, 그 안에서 await이 예상대로 작동할 것입니다:


async function printFiles () {
const files = await getFilePaths();
for (const file of files) {
const contents = await fs.readFile(file, 'utf8');
console.log(contents);
}
}

병렬로 읽기

파일을 병렬로 읽으려면 forEach를 사용할 수 없습니다. 각 async 콜백 함수 호출은 프로미스를 반환하지만, 그들을 대기하는 대신에 버리고 있습니다. 그냥 대신에 map을 사용하고, Promise.all과 함께 얻게 된 프로미스 배열을 기다릴 수 있습니다:


async function printFiles () {
const files = await getFilePaths();
await Promise.all(files.map(async (file) => {
const contents = await fs.readFile(file, 'utf8')
console.log(contents)
}));
}

답변 2

올바른 방법으로 async/await을 forEach 루프와 함께 사용하기
많은 웹 개발자들이 비동기 프로그래밍을 위해 자바스크립트의 async/await 문법을 사용하고 있습니다. 이러한 기술은 루프 문법과 함께 사용할 때 특히 유용합니다. 이번 에세이에서는 async/await을 forEach 루프와 어떻게 함께 사용하는지 알아보고, 이를 올바르게 사용하는 방법에 대해 자세히 알아보겠습니다.
먼저, forEach 루프는 배열의 각 원소에 대해 지정된 함수를 실행하는 메서드입니다. 이때 함수는 비동기적으로 실행될 수 있으며, 이런 경우 async/await을 사용하여 코드의 가독성과 디버깅을 용이하게 만들 수 있습니다.
예를 들어, DOM 요소의 배열을 반복하며 각 요소의 속성을 비동기적으로 변경해야 한다고 가정해보겠습니다. 아래는 forEach와 async/await를 함께 사용한 예시입니다.
```javascript
// 비동기 함수 정의
const changeAttributes = async (element) => {
await someAsyncOperation(element); // 비동기 작업 실행
await anotherAsyncOperation(element); // 다른 비동기 작업 실행
// 추가적인 비동기 작업 실행 가능
};
// 배열 반복
const elements = Array.from(document.querySelectorAll('.element'));
elements.forEach(async (element) => {
await changeAttributes(element); // 속성 변경 함수 실행
});
```
위의 코드에서는 changeAttributes 함수가 각 요소에 대해 비동기 작업을 수행하기 위해 async/await을 사용하고 있습니다. 또한 forEach 루프 내에서 async 함수를 호출하고 있습니다. 이렇게 함으로써 각 요소에 대한 비동기 작업이 순차적으로 실행되며, 결과적으로 코드가 더욱 명확하고 예상 가능한 방식으로 동작하게 됩니다.
하지만 한가지 주의해야 할 점은 forEach 내에서 async 함수를 호출하는 것은 지양하는 것이 좋습니다. 이는 forEach 메서드가 비동기 함수를 제대로 처리하지 않을 수 있기 때문입니다. 대신에 for...of 루프를 사용하여 반복하고, 그 안에서 async 함수를 호출하는 것을 권장합니다.
이와 함께 async/await을 forEach 루프에 적용할 때 더 좋은 성능과 가독성을 위해 몇 가지 팁을 제공하겠습니다.
첫째, 각 비동기 작업을 병렬로 실행하고 싶다면, Promise.all 메서드를 사용하여 배열의 모든 비동기 작업이 완료될 때까지 기다릴 수 있습니다. 이렇게 하면 코드 실행 시간을 단축시킬 수 있습니다.
둘째, 오류 처리를 위해 try-catch 문을 사용하는 것이 좋습니다. async 함수 내에서 오류가 발생할 경우, try 블록 내에서 오류를 처리하고 적절한 작업을 수행할 수 있습니다.
셋째, 성능을 향상시키기 위해 병렬로 실행되는 비동기 작업의 수를 제한할 수 있습니다. 너무 많은 비동기 작업을 동시에 실행하면 메모리와 성능에 부담이 될 수 있으므로, 얼마나 많은 비동기 작업을 병렬로 실행할지 결정하는 것이 중요합니다.
이처럼 async/await을 forEach 루프와 함께 사용할 때에는 주의할 점과 최적화를 위한 팁들을 알고 있어야 합니다. async/await은 코드의 가독성과 유지보수성을 높여주는 강력한 비동기 프로그래밍 도구이지만, 제대로 활용하지 않으면 원치 않는 결과를 초래할 수 있습니다. 따라서 개발자들은 async/await과 forEach 루프의 사용 방법을 잘 이해하고, 최적의 성능과 사용성을 위해 더 많은 연구와 학습에 투자해야 합니다.

반응형
Comments