JavaScriptにおけるforeachのコールバック関数の並列実行の探究

10865 ワード

私たちの正常な表裏配列操作には、for/while方式で遍歴する方法と、foreach、map、every、some、reduceなど、Array内蔵方式で遍歴する方法の2つがあります.
これらの操作処理同期のコールバック関数は、シリアルで実行されます.次に、forとforeachを例に挙げます.
//     
const arr = [1,'a',2,'b',3,'c']
//         
const foo = i => {
     
  if(typeof i === 'number'){
     
    for(let i =0;i<1000000000;i++){
     
    }
    console.log(i)
  }else{
     
    console.log(i)
  }
  return true;
}
  • for関数実行結果:
  • //   for    
    function a() {
         
      for (var i = 0; i < arr.length; i++) {
         
        foo(arr[i])
      }
    }
    a() //   :1 a 2 b 3 c
    
  • foreach実行結果:
  • // map,some,every,reduce        ,     
    function e() {
         
      arr.map((a) => foo(a))
    }
    e()  //   :1 a 2 b 3 c
    

    結論:同期タスクの両方の表現はシリアル実行である
    jsは非同期タスクに対してブラウザに渡されて並列に実行されますが、最新のES構文にはasync/await構文糖があり、非同期タスクを同期タスクの形式として実行できます.
    ではasync/awaitという非同期タスクに対して、この2つの遍歴方式はどのように実行されていますか?次の例を参照してください.
    //     
    const arr = [1,'a',2,'b',3,'c']
    //       
    const foo = i => {
         
      return new Promise((resolve, reject) => {
         
        if(typeof i === 'number'){
         
          setTimeout(() => {
         
            console.log(i)
            resolve(i)
          }, 500)
        }else{
         
          setTimeout(() => {
         
            console.log(i)
            resolve(i)
          }, 1000)
        }
      })
    }
    
  • for関数実行結果:
  • async function a() {
         
      for (var i = 0; i < arr.length; i++) {
         
        await foo(arr[i])
      }
    }
    a() //   :1 a 2 b 3 c
    
  • foreach実行結果:
  • // map,some,every,reduce        ,     
    function e() {
         
      arr.forEach(async (a) => await foo(a))
    }
    e() //   :1 2 3 a b c
    

    結論:forのようなループはasync/awaitタスクに対して依然としてシリアルで実行されているが、forEachのようなループはasync/awaitに対して並列に実行されていることがわかる.