【收藏】五種在循環中使用 async/await 的方法

咱們常常會遇到這樣的需求,在循環中使用異步請求,而 ES6 的 async/await 是咱們讓異步編程更簡單的利劍🗡。編程

本篇總結了 5 種在循環中使用 async/await 的方法(代碼乾貨都能在瀏覽器控制檯自測):數組

  • 打勾的方法 ✔:表示在循環中每一個異步請求是按照次序來執行的,咱們簡稱爲 「串行」
  • 打叉的方法 ❌ :表示只借助循環執行全部異步請求,不保證次序,咱們簡稱爲 「並行」

按需所取,點贊👍收藏📕promise

1557468265620059.png

forEach ❌

首先,想到遍歷,咱們經常使用 forEach,用 forEach 能夠嗎?來試試~瀏覽器

首先要明確的是,本質上 forEach 就是一個 for 循環的包裝。markdown

Array.prototype.forEach = function (callback) {
  for (let index = 0; index < this.length; index++) {
    callback(this[index], index, this)
  }
}
複製代碼

在回調函數內部調用 await 須要這個回調函數自己也是 async 函數,因此在【循環+ async/await】中的代碼應這樣寫:異步

async function someFunction(items) {
  items.forEach( async(i) => {
     const res = await someAPICall(i);
     console.log('--->', res);
  });
}

function someAPICall(param) {
    return new Promise((resolve, reject)=>{
      setTimeout(()=>{
        resolve("Resolved" + param)
      },param);
    })
}

someFunction(['3000','8000','1000','4000']);
複製代碼

在控制檯執行,如圖:async

async1.png

咱們能夠看到 forEach 並無串行輸出結果。forEach 只是把全部請求執行了,謂之並行異步編程

for...of... ✔

事實上 for...of 卻符合咱們串行的要求。函數

思路以下:this

async function printFiles () {
  let fileNames = ['picard', 'kirk', 'geordy', 'ryker', 'worf'];
  for (const file of fileNames) {
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  }
}
複製代碼

針對本文例,代碼以下:

async function someFunction(items) {
 for (const i of items){
     const res= await someAPICall(i)
     console.log('--->', res);
 }
}

function someAPICall(param) {
    return new Promise((resolve, reject)=>{
      setTimeout(()=>{
        resolve("Resolved" + param)
      },param);
    })
}

someFunction(['3000','8000','1000','4000']);
複製代碼

控制檯執行以下圖:

async2.png

reduce ✔

有了解過【循環】+【異步】的童鞋確定知道 reduce。它能夠稱得上是精華所在!

代碼以下:

function testPromise(time) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(`Processing ${time}`);
      resolve(time);
    }, time);
  });
}

let result = [3000,2000,1000, 4000].reduce( (accumulatorPromise, nextID) => {
  return accumulatorPromise.then(() => {
    return testPromise(nextID);
  });
}, Promise.resolve());

result.then(e => {
  console.log("All Promises Resolved !!✨")
});
複製代碼

咱們能夠使用 reduce 函數來遍歷數組並按順序 resolve promise。

很清晰!自行控制檯體驗。

generator ✔

其實用 async generator 也是能夠的。

async function* readFiles(files) {
  for(const file of files) {
    yield await readFile(file);
  }
};
複製代碼

針對本文例,代碼以下:

async function* generateSequence(items) {
  for (const i of items) {
    await new Promise(resolve => setTimeout(resolve, i));
    yield i;
  }
}

(async () => {
  let generator = generateSequence(['3000','8000','1000','4000']);
  for await (let value of generator) {
    console.log(value);
  }
})();
複製代碼

自行控制檯體驗。

Promise.all ❌

若是你不用考慮異步請求的執行順序,你能夠選擇 Promise.all(),即 Promise.all() 能夠達到 並行 的目的。它也能保證你的請求都被執行過。

async function printFiles () {
  let fileNames = ['picard', 'kirk', 'geordy', 'ryker', 'worf'];
  await Promise.all(fileNames.map(async (file) => {
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  }));
}
複製代碼

針對本文例,代碼以下:

async function promiseAll(arr) {
  await Promise.all(arr.map(async (i) => {
    await sleep(i)
    console.log('--->', i);
  }))
}

function sleep(i) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve()
    }, i)
  })
}

promiseAll(['3000','8000','1000','4000'])
複製代碼

自行控制檯體驗。


好啦~

本次總結就到這!主要是代碼部分,本身敲一敲,或者跑一跑、改一改,感覺感覺異同。

正所謂「代碼用時方恨少呀「!😄按需所取,點贊👍收藏📕。

關注個人公衆號【掘金安東尼】,持續輸出中......

相關文章
相關標籤/搜索