五种在循环中使用 async/await 的方法

更新日期: 2021-10-11阅读: 1.1k标签: async

我们经常会遇到这样的需求,在循环中使用异步请求,而 ES6 的 async/await 是我们让异步编程更容易的利剑。
本文总结了5种循环使用async/await的方法(代码可在浏览器控制台自测):

  • 打勾的方法 ✔:表示在循环中每个异步请求是按照次序来执行的,我们简称为 “串行”
  • 打叉的方法 ❌ :表示只借助循环执行所有异步请求,不保证次序,我们简称为 “并行”


forEach ❌

首先,想到遍历,我们常用 forEach,用 forEach 可以吗?来试试~

首先要明确的是,本质上 forEach 就是一个 for 循环的包装。

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']);

在控制台执行,我们可以看到 forEach 并没有串行输出结果。forEach 只是把所有请求执行了,谓之并行


for...of... ✔

事实上 for...of 却符合我们串行的要求。

思路如下:

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']);

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'])

自行控制台体验。

文章来自于公众号「掘金安东尼」

链接: https://www.fly63.com/article/detial/10710

JS中的async/await的执行顺序详解

虽然大家知道async/await,但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 JavaScript 的 async/await

ES6新特性Async

Async实际上是一个封装了自动化执行并返回一个Promise的Generator函数的语法糖。这句话的意思我们可以分为三个部分来解读:首先它有一个自动化执行,Generator函数是依靠不停的调用.net来依次执行的,Async有一个自动化执行的过程

Node.js Async 函数最佳实践

Node.js7.6起, Node.js 搭载了有async函数功能的V8引擎。当Node.js 8于10月31日成为LTS版本后,我们没有理由不使用async函数。接下来,我将简要介绍async函数,以及如何改变我们编写Node.js应用程序的方式。

将async/await编译到 ES3/ES5 (外部帮助库)

自2015年11 发布1.7版以来,TypeScript 已支持 async/await 关键字。编译器使用 yield 将异步函数转换为生成器函数。这意味着咱们无法针对 ES3 或 ES5,因为生成器仅在 ES6 中引入的。

你可能忽略的 async/await 问题

async/await 大家肯定都用过,在处理异步操作的时候真的是很方便。那今天主要讲一些在使用 async/await 时容易忽略和犯错的地方。上面的代码中,每一行都会 等待上一行的结果返回后才会执行。

使用async await通过for循环在图片onload加载成功后获取成功的图片地址

有一个图片列表,我想要在图片onload成功之后获取加载成功的图片列表,图片资源加载为异步,我们使用ES7的async await方式实现,多张图片,是用for循环。

ES8 Async 和 Await

Async 和 Awaiit 是 Promise 的扩展,我们知道 JavaScript 是单线程的,使用 Promise 之后可以使异步操作的书写更简洁,而 Async 使 Promise 像同步操作

有了 Promise 和 then,为什么还要使用 async?

最近代码写着写着,我突然意识到一个问题——我们既然已经有了 Promise 和 then,为啥还需要 async 和 await?这不是脱裤子放屁吗?

手写async await的最简实现

如果让你手写async函数的实现,你是不是会觉得很复杂?这篇文章带你用20行搞定它的核心。经常有人说async函数是generator函数的语法糖,那么到底是怎么样一个糖呢?让我们来一层层的剥开它的糖衣。

认识async/await

async/await是ES7的写法,可以让非同步call back写法看起来像同步的顺序去执行。以下我们new一个Promise的class并return给一个function

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!