오용하기 쉬운 Promise.all

17060 단어 JavaScriptpromisetech
비동기 처리를 병행하는 것은 매우 편리하다Promise.all(). 그러나 때때로 부주의로 사용하는 행위가 나타난다.

총결산

  • Promise.all 내에서 함수를 정의할 때 함수 공식을 즉시 실행하지 않으면 실행하지 않습니다
  • Promise.all에 전달될 때await에 무의식적으로 직렬 처리가 된다
  • 샘플 코드


    아래 코드에서 예를 들어 설명한 ①, ②, ③, ④ 중 일부 행위는 기대에 부합되지 않는다.
    (모든 실행에 오류 없음)
    let response;
    
    const syncFn = () => {};
    const asyncFn = async () => {};
    
    const results = await Promise.all([
      // ①
      syncFn(),
      
      // ②
      asyncFn(),
    
      // ③
      async () => {
        const data = await fetchData();
        await nextProcess(data);
      },
    
      // ④
      await asyncFn(),
    ]);
    
    그 중에서 ③·④는 의도적인 행위가 아니다.

    Promise.프로미스를 올에게 맡기다

    Promise.all 대기 상태의 Promise를 전달하고 각 Promise의 해결을 기다린다.
    https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
    여기서 주의해야 할 것은'전달을 실행하는 함수가 아니다'는 것이다.
    따라서 샘플 코드 ③는 원래 아무 일도 일어나지 않는다.
    const results = await Promise.all([
      // 関数は実行されない
      async () => {
        const data = await fetchData();
        await nextProcess(data);
      },
    ]);
    
    이 코드는 Promise가 아니라 함수 자체가 전달되기 때문에 결과 함수도 되돌아온다.
    results[0] === async () => {
      const data = await fetchData();
      await nextProcess(data);
    }
    
    Promise.all의 매개 변수에서 함수를 정의하려면 즉시 실행 함수 공식으로 설명해야 한다.
    const results = await Promise.all([
      // 関数内の処理が実行される
      (async () => {
        const data = await fetchData();
        await nextProcess(data);
      })(),
    ]);
    

    매개변수 내에서 Promise의 해결을 기다리지 않음


    견본 코드 ④에서 Promise.all의 매개 변수 안에는 Promiseawait가 있다.
    이때 실제 전달Promise.all된 것은 asyncFn() 함수의 반환값이기 때문에 대기 중인 프로미스가 아니다.
    const results = await Promise.all([
      await asyncFn(),
    ]);
    
    예를 들어 아래 코드는 3개의 비동기 함수를 병행하여 실행하는 것처럼 보이지만 각자의 함수가 전달될 때Promise를 해결하고 그 결과는 직렬 실행이다.
    const sleep30s = async () => { await sleep(30); console.log('sleep 30s'); };
    const sleep100s = async () => { await sleep(100); console.log('sleep 100s'); };
    const sleep60s = async () => { await sleep(60); console.log('sleep 60s'); };
    
    await Promise.all([
      await sleep30s(),
      await sleep100s(),
      await sleep60s(),
    ]);
    
    // 実行結果:
    //   sleep 30s
    //   sleep 100s
    //   sleep 60s
    
    병렬 처리를 하려면 비동기 함수를 되돌아오는 대기 상태의 프로미스를 Promise.all에 전달해야 하기 때문에 await할 수 없다.
    const sleep30s = async () => { await sleep(30); console.log('sleep 30s'); };
    const sleep100s = async () => { await sleep(100); console.log('sleep 100s'); };
    const sleep60s = async () => { await sleep(60); console.log('sleep 60s'); };
    
    await Promise.all([
      sleep30s(),
      sleep100s(),
      sleep60s(),
    ]);
    
    // 実行結果:
    //   sleep 30s
    //   sleep 60s
    //   sleep 100s
    

    좋은 웹페이지 즐겨찾기