使用 async await + setTimeout 分割 while 循环

本文介绍了如何利用JavaScript的async/await和setTimeout处理CPU密集型任务,特别是大数组排序,以避免阻塞页面渲染。通过任务分割,将while循环拆分成多个小任务,从而实现流畅的用户体验。文中提供了实际代码示例,并链接到CodePen的对比效果展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于JavaScript单线程的特性,在执行CPU密集型任务时(如大数组排序)会阻塞网页的渲染,解决办法一般是使用setTimeout函数对任务进行分割,或者把这类任务交由 web worker 处理。今天遇到一个对大数组排序的问题,需要使用任务分割来避免阻塞,在这里记录下我的实现方法。在实现时我将 while 语句进行了分割,避免出现大循环体语句一直进行计算,主要代码如下:

    //while 控制语句进行分割
    // expression 相当于 while 的条件判断
    // statement 相当于 while 循环体语句
    async function while_async(expression, statement){
        while(expression()){
            await while_seg(expression, statement);
        }
    }

    let while_seg = (expression, statement) => new Promise((resolve, reject) => {
        setTimeout(()=>{
            let i = 0;
            let while_size = 50000;
            while(expression()){
                i++;
                statement();
                // 如果 while 内循环次数大于 while_size ,则进入事件循环
                if(i>while_size)break;
            }
            resolve();
        }, 0);
    });

应用在大数组排序上,效果对比可以在这里查看:https://codepen.io/liuyaqi/pen/dmZdPe

height="351" width="650" scrolling="no" title="while_seg" src="//codepen.io/liuyaqi/embed/dmZdPe/?height=351&theme-id=0&default-tab=result&embed-version=2" allowfullscreen="true">See the Pen <a href="https://codepen.io/liuyaqi/pen/dmZdPe/">while_seg</a> by liuyaqi (<a href="https://codepen.io/liuy
<think>我们首先需要介绍Promise、Generator和Async/Await的基本概念和用法,然后展示它们如何结合使用,最后提出相关问题。 注意:按照规则,在回答末尾必须输出“§§相关问题§§”并列出3-5个相关问题。 内容安排: 1. Promise:解决回调地狱,提供then和catch方法。 2. Generator:可以暂停和恢复的函数,通过yield实现,通常与co库或手动执行器结合使用。 3. Async/Await:基于Generator和Promise的语法糖,使异步代码看起来像同步。 然后展示如何结合使用,以及从Generator+Promise到Async/Await的演进。 注意:由于问题要求,我们最后要输出相关问题。</think>### JavaScript 异步编程演进:Promise → Generator → Async/Await #### 核心概念对比 | 技术 | 特点 | 适用场景 | |---------------|------------------------------|----------------------------| | **Promise** | 链式调用(`.then/.catch`) | 简单异步操作、多异步并行 | | **Generator** | 暂停/恢复执行(`yield`/`next`) | 复杂流程控制、惰性求值 | | **Async** | 语法糖(`async`/`await`) | 同步化异步代码、错误处理简化 | --- ### 深度解析与代码示例 #### 1. Promise 基础应用 ```javascript // 创建Promise const fetchData = (url) => new Promise((resolve, reject) => { setTimeout(() => { Math.random() > 0.3 ? resolve(`Data from ${url}`) : reject('Network error'); }, 300); }); // 链式调用 fetchData('/api/user') .then(data => { console.log(data); return fetchData('/api/profile'); }) .then(profile => console.log(profile)) .catch(err => console.error(err)); // 统一错误处理 ``` #### 2. Generator + Promise 协作 ```javascript function* asyncGenerator() { try { const user = yield fetchData('/api/user'); console.log(user); const profile = yield fetchData('/api/profile'); console.log(profile); } catch (err) { console.error('Generator error:', err); } } // 执行器函数 function runGenerator(gen) { const g = gen(); function handle(result) { if (result.done) return; result.value .then(data => handle(g.next(data))) .catch(err => g.throw(err)); } handle(g.next()); } runGenerator(asyncGenerator); // 自动执行生成器 ``` #### 3. Async/Await 终极方案 ```javascript async function fetchUserData() { try { const user = await fetchData('/api/user'); console.log(user); const profile = await fetchData('/api/profile'); console.log(profile); // 并行请求 const [data1, data2] = await Promise.all([ fetchData('/api/posts'), fetchData('/api/comments') ]); } catch (err) { console.error('Async error:', err); } } // 自执行异步函数 (async () => { await fetchUserData(); })(); ``` --- ### 进阶技巧与最佳实践 #### 1. 错误处理优化 ```javascript // 高阶函数封装错误处理 const safeAwait = (promise) => promise.then(data => [null, data]).catch(err => [err]); async function main() { const [err, data] = await safeAwait(fetchData('/api')); if (err) return fallbackHandler(); // 正常处理data } ``` #### 2. Generator 实现无限数据流 ```javascript function* dataStream() { let page = 1; while(true) { yield fetch(`/api/items?page=${page++}`); } } // 消费流 async function processStream() { const stream = dataStream(); for(let i=0; i<5; i++) { const res = await stream.next().value; console.log(await res.json()); } } ``` #### 3. Async 性能优化 ```javascript // 错误示例:顺序await导致性能下降 async function slowFetch() { const a = await fetch('/a'); // 阻塞 const b = await fetch('/b'); // 阻塞 } // 正确优化:并行请求 async function fastFetch() { const [a, b] = await Promise.all([fetch('/a'), fetch('/b')]); } ``` --- ### 演化关系图示 ``` 回调地狱 → Promise(链式管理) → Generator(流程控制) → Async/Await(终极方案) ↑____________协作实现___________↑ ``` ### 浏览器兼容方案 ```html <!-- 旧浏览器支持 --> <script src="https://cdn.jsdelivr.net/npm/regenerator-runtime@0.13.11/runtime.min.js"></script> <script> // Babel转换后的async代码会依赖此runtime </script> ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值