forEach - async/await 관련 에러
서비스 코드
async getNACLInfo() {
let naclInfoArr: Object[] = [];
const vpcsArr = this.getVPCInfo();
return (await vpcsArr).forEach(async (vpc: any) => {
// console.log(vpc.VpcId);
const vpcId = vpc.VpcId;
const command = new DescribeNetworkAclsCommand({
Filters: [
{
Name: 'vpc-id',
Values: [vpcId],
},
],
});
try {
const response = await this.ec2Client.send(command);
// console.log(response.NetworkAcls);
response.NetworkAcls.forEach((networkAcl: any) => {
const naclEntries = networkAcl.Entries.filter(
(entry: any) =>
entry.Egress === false &&
entry.RuleNumber >= 100 &&
entry.RuleNumber <= 32766,
);
naclInfoArr.push(naclEntries);
});
} catch (error) {
console.error(`error = `, error);
}
});
return naclInfoArr;
}
컨트롤러 코드
@Get('NACL-info')
async getNACLInfo() {
const report = await this.awsService.getNACLInfo();
console.log(report);
return { NACL_info: report };
}
위 API를 실행하였을 때, 결과값으로 빈 배열이 나오는 문제가 있다. 문제의 이유와 해결책을 찾아보자.
위 코드의 문제는 forEach 메서드가 async/await와 함께 사용될 때 기대한 대로 작동하지 않기 때문이다. forEach는 루프 내부의 프로미스가 해결되기를 기다리지 않고 예상한 값 대신에 undefined를 반환한다. (그래서 controller코드에서 반환할 값을 콘솔을 찍어보면 undefined가 나온 것이다.)
이 문제를 해결하려면 forEach 대신에 map 메서드를 사용하고 결과로 나온 프로미스 배열에 대해 await를 사용해야 한다. 이렇게 하면 루프 내부의 모든 프로미스가 해결될 때까지 기다린 다음 최종 결과를 반환한다.
async getNACLInfo() {
let naclInfoArr: Object[] = [];
const vpcsArr = await this.getVPCInfo();
await Promise.all(
vpcsArr.map(async (vpc: any) => {
const vpcId = vpc.VpcId;
const command = new DescribeNetworkAclsCommand({
Filters: [
{
Name: 'vpc-id',
Values: [vpcId],
},
],
});
try {
const response = await this.ec2Client.send(command);
response.NetworkAcls.forEach((networkAcl: any) => {
const naclEntries = networkAcl.Entries.filter(
(entry: any) =>
entry.Egress === false &&
entry.RuleNumber >= 100 &&
entry.RuleNumber <= 32766,
);
naclInfoArr.push(naclEntries);
});
} catch (error) {
console.error(`error = `, error);
}
}),
);
return naclInfoArr;
}
위와 같이 코드를 수정하면 다음과 같이 컨트롤러에서 올바른 값이 리턴된다.
{
"NACL_info": [
[
{
"CidrBlock": "0.0.0.0/0",
"Egress": false,
"Protocol": "-1",
"RuleAction": "allow",
"RuleNumber": 100
}
],
.
.
.
[
{
"CidrBlock": "0.0.0.0/0",
"Egress": false,
"Protocol": "-1",
"RuleAction": "allow",
"RuleNumber": 100
}
]
]
}