forEach/map 및 async는 함께 사용되지 않습니다.

May 07 2023
때때로 우리는 종종 forEach 및 map 함수와 함께 비동기 함수를 전달하는 경향이 있습니다. 예: 결과: 1부터 모든 숫자.
머리글

때때로 우리는 종종 forEach 및 map 함수와 함께 비동기 함수를 전달하는 경향이 있습니다.

예를 들어:

[1,2,3,4,5].forEach(async (n) => setTimeout(console.log(n), 1000));

결과: 1..5의 모든 숫자가 차례로 인쇄되지만각 라인을 인쇄한 후 1초의 간격이 없습니다 .

왜 이런 일이 발생합니까?

이 javascipt 함수를 살펴보십시오.

async function doubleOf(n) {
  return n*2;
}

결과: 이것은 실제로 숫자로 확인되는 Promise를 반환합니다.

엄격한 유형을 사용하여 이 함수에 해당하는 TypeScript를 작성하면 상황이 명확해집니다.

다음 코드는 컴파일 되지 않습니다 .

async function doubleOf(n: number): number {
  return n*2;
}

올바른 버전은 다음과 같습니다.

async function doubleOf(n: number): Promise<number> {
  return n*2;
}

async-await에서 제공하는 구문 설탕에 속지 마십시오. 비동기를 사용하지 않고 순수한 약속을 작성했다면 위의 함수는 다음과 같습니다.

function doubleOf(n) {
  return new Promise((resolve) => resolve(n*2));
}

function doubleOf(n: number): Promise<number> {
  return new Promise((resolve) => resolve(n*2));
}

비동기 함수는 값이 아닌 약속을 반환합니다.
  1. doubleOf숫자를 입력받아 숫자를 반환하는 함수가 있습니다 . 평범한 오래된 자바 스크립트.
  2. doubleOfOldWay숫자를 받아서 숫자로 확인되는 약속을 반환하는 함수가 있습니다 .
  3. doubleOfNewWay숫자를 받아 숫자를 반환하는 것처럼 보이지만 실제로는 doubleOfOldWay함수 처럼 숫자로 확인되는 약속을 반환하는 비동기 함수가 있습니다 .
  4. doubleOfOldWaydoubleOfNewWay기능은 완전히 동일합니다.
  5. 따라서 doubleOfOldWaydoubleOfNewWay함수에서 반환된 값에 대해 곱하기 연산을 실행하려고 하면 결과는 입니다 NaN. 다중 약속을 할 수 없기 때문입니다(확실히!).
  6. 곱하고 : doubleOfOldWay_doubleOfNewWay

초기 예제로 돌아가서:

[1,2,3,4,5].forEach(async (n) => setTimeout(console.log(n), 1000));

이 forEach 함수에서 기대하는 것을 구현하는 가장 정확한 방법은 간단한 for 루프를 사용하는 것입니다.

for(const number of [1,2,3,4,5]) {
    console.log(number);
    await new Promise(resolve => setTimeout(resolve, 1000)); // Sleep for "atleast" 1 second
}

[1,2,3,4,5].map(async (n) => n*2);

(5) [Promise, Promise, Promise, Promise, Promise]
0: Promise {<fulfilled>: 2}
1: Promise {<fulfilled>: 4}
2: Promise {<fulfilled>: 6}
3: Promise {<fulfilled>: 8}
4: Promise {<fulfilled>: 10}

각 숫자의 double 목록을 얻기 위해 우리가 할 수 있는 일은 다음과 같습니다.

await Promise.all([1,2,3,4,5].map(async (n) => n*2));

[2, 4, 6, 8, 10]