鸿蒙 promise 一个线程同时发送多个请求的原理(二)

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

鸿蒙应用开发中,虽然JavaScript是单线程运行的,但可以通过 事件循环机制异步I/O 实现"伪并发"的多个HTTP请求。

一、单线程并发请求的核心原理

1. 事件循环机制

2. 关键点说明
  • 非阻塞I/O:实际网络请求由底层系统线程处理
  • Promise微任务.then()回调进入微任务队列
  • 并发本质:请求发送是并行的,回调处理是串行的

二、实现单线程"并发"的3种方式

方法1:Promise.all + fetch(推荐)
import http from '@ohos.net.http';

async function concurrentRequests(urls: string[]) {
  // 1. 创建多个未解决的Promise
  const requests = urls.map(url => {
    return new Promise((resolve, reject) => {
      const httpRequest = http.createHttp();
      httpRequest.request(
        url,
        {
          method: 'GET',
          connectTimeout: 5000
        },
        (err, data) => {
          httpRequest.destroy();
          err ? reject(err) : resolve(data.result);
        }
      );
    });
  });

  // 2. 等待所有请求完成
  try {
    const results = await Promise.all(requests);
    results.forEach((res, index) => {
      console.log(`请求${urls[index]}结果:`, res);
    });
  } catch (e) {
    console.error('某个请求失败:', e);
  }
}

// 使用示例
const apiUrls = [
  'https://api.example.com/data1',
  'https://api.example.com/data2',
  'https://api.example.com/data3'
];
concurrentRequests(apiUrls);
方法2:for...of + await(可控并发)
async function controlledConcurrent(urls: string[], maxConcurrent = 3) {
  const results = [];
  const executing = new Set();

  for (const url of urls) {
    // 1. 创建Promise但不立即await
    const promise = new Promise((resolve, reject) => {
      const httpRequest = http.createHttp();
      httpRequest.request(url, (err, data) => {
        httpRequest.destroy();
        err ? reject(err) : resolve(data.result);
      });
    });

    // 2. 记录执行中的Promise
    const task = promise.finally(() => {
      executing.delete(task);
    });
    executing.add(task);

    // 3. 控制并发数
    if (executing.size >= maxConcurrent) {
      await Promise.race(executing);
    }
  }

  // 4. 等待剩余任务
  return Promise.all([...executing]);
}
方法3:Promise.allSettled(获取全部结果)
async function allSettledRequests(urls: string[]) {
  const requests = urls.map(url => {
    return new Promise((resolve) => {
      const httpRequest = http.createHttp();
      httpRequest.request(url, (err, data) => {
        httpRequest.destroy();
        resolve({
          url,
          status: err ? 'rejected' : 'fulfilled',
          data: err || data.result
        });
      });
    });
  });

  return await Promise.allSettled(requests);
}

三、底层原理深度解析

1. libuv事件循环

鸿蒙使用的JS引擎通过libuv实现:

  • 网络I/O:由系统线程池处理(Windows使用IOCP,Linux用epoll)
  • 回调队列:分为宏任务队列和微任务队列
  • 典型执行顺序
  同步代码 → 微任务队列 → 宏任务队列 → 渲染更新

 2. HTTP请求生命周期

3. 性能瓶颈点
环节优化方向
DNS解析使用DNS缓存
TCP连接建立保持长连接
线程池竞争控制并发数
JSON解析流式解析器
回调处理减少主线程阻塞操作

四、与多线程方案的对比

特性单线程PromiseTaskPool多线程
CPU利用率低(主线程串行)高(多核并行)
内存开销较大(每个线程独立)
适用场景IO密集型CPU密集型
开发复杂度简单中等
典型延迟1-100ms10-500ms

建议

  1. IO密集型任务:优先使用单线程Promise并发
  2. 超过50个请求:考虑分片处理(每片5-10个)
  3. 关键路径请求:使用Promise.race()实现快速失败

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值