JavaScript 中的异步并发

2022/11/4 6:24:52

本文主要是介绍JavaScript 中的异步并发,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

我最近的任务是构建一个微服务,该服务需要发出数千个HTTP请求并处理响应。为了创建这种情况的简单模拟,我将使用一个 fake 函数,该函数接受任意值并返回解析为包含值和间隔的对象:requestPromise

const {promisify} = require('util')
const sleep = promisify(setTimeout)const request = async(data) => {
  let time = Math.random() * 1000
  await sleep(time)
  return {data, time}
}

我有一堆包含请求参数数据的记录,所以我做的第一件事就是查询这些记录。对于此示例,我们将使用整数数组来模拟记录。我的第一直觉(我经验不足)是遍历记录数组,发出每个HTTP请求并将结果推送到新数组:

async function main() {
  const records = Array.from(new Array(10)).map((e, i) => i)
  let responses = []
  console.time('Inline')
  for (let i = 0; i < records.length; i++) {
    let response = await request(records[i])
    responses.push(response)
  }
  console.log(JSON.stringify(responses, null, 2))
  console.timeEnd('Inline')
}

这工作正常,但我们必须在发出下一个请求之前等待每个响应,这意味着这可能需要长达 10 秒才能执行。结果如下所示:

[
  {     
    "data": 0,
    "time": 48.95140139293264
  },
  {
    "data": 1,
    "time": 351.42969859007377
  },
  ...
]
Inline: 5210.4460449ms

5秒是一段很长的时间。现在让我们看看如何同时执行这些请求。我们可以将每个调用推送到一个数组中,并使用 Promise.all() 等待它们全部解析:request

async function main() {
  const records = Array.from(new Array(10)).map((e, i) => i)
  console.time('Concurrent')
  let promises = []
  for (let i = 0; i < records.length; i++) {
    promises.push(request(records[i]))
  }
  let responses = await Promise.all(promises)
  console.log(JSON.stringify(responses, null, 2))
  console.timeEnd('Concurrent')
}

瞧,我们刚刚加快了服务速度!结果如下所示:records.length

[
  {
    "data": 0,
    "time": 160.08417354131944
  },
  {
    "data": 1,
    "time": 560.08495847237463
  },
  ...,
  {
    "data": 9,
    "time": 223.39482395749209
  }
]
Concurrent: 560.08495847237463ms

使用这种非阻塞方法会在所有承诺全部完成后立即获取它们的结果,因此总执行时间仅比最慢的 HTTP 请求大几毫秒。此相同技术可用于任何异步操作集合。responses

只是为了好玩,让我们在一行中使用Array.map:

let responses = await Promise.all(records.map(record => request(record)))

我希望这有帮助,快乐编码。



这篇关于JavaScript 中的异步并发的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程