• <strike id="6sogq"><s id="6sogq"></s></strike>
  • <strike id="6sogq"></strike>

    千鋒教育-做有情懷、有良心、有品質的職業教育機構

    400-811-9990
    手機站
    千鋒教育

    千鋒學習站 | 隨時隨地免費學

    千鋒教育

    掃一掃進入千鋒手機站

    領取全套視頻
    千鋒教育

    關注千鋒學習站小程序
    隨時隨地免費學習課程

    上海
    • 北京
    • 鄭州
    • 武漢
    • 成都
    • 西安
    • 沈陽
    • 廣州
    • 南京
    • 深圳
    • 大連
    • 青島
    • 杭州
    • 重慶
    當前位置:成都千鋒IT培訓  >  技術干貨  >  forEach中的await

    forEach中的await

    來源:千鋒教育
    發布人:gxy
    時間: 2023-04-11 16:33:47

      forEach中的await

    forEach中的await

      不知道你是否寫過類似的代碼:

      function test() {

      let arr = [3, 2, 1]

      arr.forEach(async item => {

      const res = await fetch(item)

      console.log(res)

      })

      console.log('end')

      }

      function fetch(x) {

      return new Promise((resolve, reject) => {

      setTimeout(() => {

      resolve(x)

      }, 500 * x)

      })

      }

      test()

      復制代碼

      

      我當時期望的打印順序是

      3

      2

      1

      end

      結果現實與我開了個玩笑,打印順序居然是

      end

      1

      2

      3

      為什么?

      復制代碼

      其實原因很簡單,那就是 forEach 只支持同步代碼。

      我們可以參考下 Polyfill 版本的 forEach,簡化以后類似就是這樣的偽代碼

      while (index < arr.length) {

      callback(item, index) //也就是我們傳入的回調函數

      }

      復制代碼

      從上述代碼中我們可以發現,forEach 只是簡單的執行了下回調函數而已,并不會去處理異步的情況。并且你在 callback 中即使使用 break 也并不能結束遍歷。

      怎么解決?

      一般來說解決的辦法有2種,for...of和for循環。

      使用 Promise.all 的方式行不行,答案是: 不行

      async function test() {

      let arr = [3, 2, 1]

      await Promise.all(

      arr.map(async item => {

      const res = await fetch(item)

      console.log(res)

      })

      )

      console.log('end')

      }

      復制代碼

      可以看到并沒有按照我們期望的輸出。

      這樣可以生效的原因是 async 函數肯定會返回一個 Promise 對象,調用 map 以后返回值就是一個存放了 Promise 的數組了,這樣我們把數組傳入 Promise.all 中就可以解決問題了。但是這種方式其實并不能達成我們要的效果,如果你希望內部的 fetch 是順序完成的,可以選擇第二種方式。

      第1種方法是使用 for...of

      async function test() {

      let arr = [3, 2, 1]

      for (const item of arr) {

      const res = await fetch(item)

      console.log(res)

      }

      console.log('end')

      }

      復制代碼

      這種方式相比 Promise.all 要簡潔的多,并且也可以實現開頭我想要的輸出順序。

      但是這時候你是否又多了一個疑問?為啥 for...of 內部就能讓 await 生效呢。

      因為 for...of 內部處理的機制和 forEach 不同,forEach 是直接調用回調函數,for...of 是通過迭代器的方式去遍歷。

      async function test() {

      let arr = [3, 2, 1]

      const iterator = arr[Symbol.iterator]()

      let res = iterator.next()

      while (!res.done) {

      const value = res.value

      const res1 = await fetch(value)

      console.log(res1)

      res = iterator.next()

      }

      console.log('end')

      }

      復制代碼

      第2種方法是使用 for循環

      async function test() {

      let arr = [3, 2, 1]

      for (var i=0;i

      const res = await fetch(arr[i])

      console.log(res)

      }

      console.log('end')

      }

      function fetch(x) {

      return new Promise((resolve, reject) => {

      setTimeout(() => {

      resolve(x)

      }, 500 * x)

      })

      }

      test()

      復制代碼

      第3種方法是使用 while循環

      async function test() {

      let arr = [3, 2, 1]

      var i=0;

      while(i!==arr.length){

      const res = await fetch(arr[i])

      console.log(res)

      i++;

      }

      console.log('end')

      }

      function fetch(x) {

      return new Promise((resolve, reject) => {

      setTimeout(() => {

      resolve(x)

      }, 500 * x)

      })

      }

      test()

      復制代碼

      要想在循環中使用async await,請使用for...of 或者 for 循環, while循環

      forEach支持async await

      forEach 在正常情況像下面這么寫肯定是做不到同步的,程序不會等一個循環中的異步完成再進行下一個循環。原因很明顯,在上面的模擬中,while 循環只是簡單執行了 callback,所以盡管 callback 內使用了 await ,也只是影響到 callback 內部。

      arr.myforeach(async v => {

      await fetch(v);

      });

      復制代碼

      要支持上面這種寫法,只要稍微改一下就好

      Array.prototype.myforeach = async function (fn, context = null) {

      let index = 0;

      let arr = this;

      if (typeof fn !== 'function') {

      throw new TypeError(fn + ' is not a function');

      }

      while (index < arr.length) {

      if (index in arr) {

      try {

      await fn.call(context, arr[index], index, arr);

      } catch (e) {

      console.log(e);

      }

      }

      index ++;

      }

      };

    聲明:本站稿件版權均屬千鋒教育所有,未經許可不得擅自轉載。

    猜你喜歡LIKE

    小程序路由跳轉

    2023-04-06

    經典面試題:static加載機制你知道嗎?

    2023-03-23

    如何做用戶分層?

    2022-12-12

    最新文章NEW

    說說React中onClick綁定后的工作原理

    2023-04-07

    說說gulp和webpack的區別

    2023-04-06

    跨域如何解決

    2023-04-04

    相關推薦HOT

    更多>>

    快速通道 更多>>

    最新開班信息 更多>>

    網友熱搜 更多>>