JS 异步函数优化!

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

JavaScript 中的异步编程是解决 I/O 密集型操作(如网络请求、文件读写等)问题的有效方式。随着现代 Web 应用的复杂性不断提升,合理的异步函数优化对于提高性能和用户体验至关重要。这里我们将介绍一些常用的异步函数优化方法。

1. 使用 async/await 语法简化异步操作

async/await 是 JavaScript 中用于处理异步操作的现代语法,它比传统的回调函数(callback)和 Promise 链式调用更易读,更易于理解,能够让异步代码像同步代码一样简洁明了。

优化点:
  • 同步风格的代码async/await 让异步代码的写法更像同步代码,避免了回调地狱(callback hell)。
  • 捕获异常try/catch 可以直接用来捕获异步函数中的错误,避免了手动链式处理每个Promise的异常。
代码示例:
// 使用 async/await 简化异步操作
async function fetchData() {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
}
fetchData();

2. 并行执行多个异步操作

如果有多个异步操作可以并行执行,使用 Promise.all()Promise.allSettled() 可以大大提高性能。这种方法可以减少等待时间,避免按顺序执行时带来的不必要延迟。

优化点:
  • 并行化异步任务:通过并行执行多个任务,能显著减少总执行时间,尤其是独立的异步请求。
  • 错误捕获Promise.all() 会在任何一个 Promise 失败时终止执行,可以用 Promise.allSettled() 来确保所有任务执行完毕,适合场景中无论成功与否都希望最终得到执行结果时。
代码示例:
// 使用 Promise.all 并行执行多个异步操作
async function fetchMultipleData() {
  const [data1, data2, data3] = await Promise.all([
    fetch('https://jsonplaceholder.typicode.com/posts'),
    fetch('https://jsonplaceholder.typicode.com/users'),
    fetch('https://jsonplaceholder.typicode.com/comments')
  ]);

  const posts = await data1.json();
  const users = await data2.json();
  const comments = await data3.json();

  console.log(posts, users, comments);
}

fetchMultipleData();

3. 限制并发量(节流控制)

有时你需要控制并发请求的数量,避免一次发起太多请求导致服务器压力过大或浏览器性能下降。使用节流控制(Throttle Control)来限制同时发起的异步请求数量。

优化点:
  • 控制并发量:避免并发请求过多,降低服务器或客户端的压力。
  • 提高资源使用效率:通过合理分配请求的发起时机,优化资源使用。
代码示例:
// 限制并发量的实现示例
async function limitedConcurrencyFetch(urls, limit) {
  const results = [];
  const queue = [];

  for (let i = 0; i < urls.length; i++) {
    const fetchPromise = fetch(urls[i]).then(response => response.json());
    queue.push(fetchPromise);

    // 当并发请求数大于限制时,等待最早完成的一个请求
    if (queue.length >= limit) {
      await Promise.race(queue);
    }

    const result = await fetchPromise;
    results.push(result);
  }

  return results;
}

const urls = [
  'https://jsonplaceholder.typicode.com/posts/1',
  'https://jsonplaceholder.typicode.com/posts/2',
  'https://jsonplaceholder.typicode.com/posts/3',
  'https://jsonplaceholder.typicode.com/posts/4',
  'https://jsonplaceholder.typicode.com/posts/5'
];

limitedConcurrencyFetch(urls, 2).then(console.log);

4. 延迟执行(Debounce)

在某些情况下,异步操作可能会因为频繁触发而造成性能问题。例如,用户输入搜索框时每打一个字就触发请求,实际上我们只关心用户停止输入时的请求。Debounce 技术可以帮助我们减少不必要的异步操作。

优化点:
  • 延迟执行:当用户持续输入时,延迟执行异步请求,直到停止输入达到设定的时间后再发起请求。
  • 减少不必要的请求:避免每次用户输入都触发请求,提高性能。
代码示例:
// 使用 Debounce 实现输入延迟触发请求
function debounce(fn, delay) {
  let timeout;
  return function (...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  };
}

const fetchSearchResults = debounce(async (query) => {
  const response = await fetch(`https://api.example.com/search?q=${query}`);
  const data = await response.json();
  console.log(data);
}, 500);

// 监听输入事件
document.getElementById('search').addEventListener('input', (e) => {
  fetchSearchResults(e.target.value);
});

5. 优化错误处理

对于异步操作的错误处理,要特别小心。多个异步操作的失败可能会影响应用的正常运行,因此我们可以使用 Promise.allSettled() 来确保无论成功还是失败都能获取所有的结果,并及时处理错误。

优化点:
  • 全局捕获:使用Promise.allSettled()来确保在所有请求完成时获取结果,即使其中某些请求失败。
  • 集中管理错误:通过集中管理错误,避免多次冗余的错误处理。
代码示例:
async function fetchAllData() {
  const urls = [
    'https://jsonplaceholder.typicode.com/posts',
    'https://jsonplaceholder.typicode.com/users',
    'https://jsonplaceholder.typicode.com/comments'
  ];

  const results = await Promise.allSettled(
    urls.map(url => fetch(url).then(res => res.json()))
  );

  results.forEach((result, index) => {
    if (result.status === 'fulfilled') {
      console.log(`Request ${index + 1} succeeded with:`, result.value);
    } else {
      console.error(`Request ${index + 1} failed with:`, result.reason);
    }
  });
}

fetchAllData();

6. 通过 async/await 实现串行化异步任务

有时,你需要串行执行异步任务。在这种情况下,async/await 是一个非常好的选择,可以按顺序执行异步操作,保证任务按预定的顺序执行。

优化点:
  • 串行化异步操作:按照指定顺序执行异步任务,避免并发操作的复杂性。
  • 确保顺序:即使异步操作之间没有依赖关系,也可以根据业务需求确保它们的执行顺序。
代码示例:
async function executeTasksInOrder() {
  await task1(); // 等待任务1完成
  await task2(); // 等待任务2完成
  await task3(); // 等待任务3完成
}

function task1() {
  return new Promise(resolve => setTimeout(() => { console.log('Task 1 done'); resolve(); }, 1000));
}

function task2() {
  return new Promise(resolve => setTimeout(() => { console.log('Task 2 done'); resolve(); }, 2000));
}

function task3() {
  return new Promise(resolve => setTimeout(() => { console.log('Task 3 done'); resolve(); }, 1500));
}

executeTasksInOrder();

总结

优化 JavaScript 异步函数的性能可以从多个方面着手:

  1. 使用 async/await 简化异步操作:提高代码可读性和可维护性。
  2. 并行执行异步任务:使用 Promise.all() 实现并行操作,减少等待时间。
  3. 限制并发量(节流控制):合理控制异步请求的并发量,避免系统资源过度消耗。
  4. 使用 debounce 降低异步调用频率:避免频繁触发异步请求,优化用户体验。
  5. 优化错误处理:通过 Promise.allSettled() 来确保处理所有请求的结果,无论是成功还是失败。

通过这些优化手段,你可以使异步函数的执行更加高效,并提升整体应用的性能和响应速度。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值