2048
登录
没  有  难  学  的  前  端
登 录
×
<返回上一级

async/await 真不是你想象中那么简单

typescriptcsshtmljavascript作者:猿2048志愿者

先上代码

公共代码

function getData(data, time) {
                return new Promise(function (resolve, reject) {
                    setTimeout(function () {
                        resolve(data);
                    }, time)
                })
            }
            let results = [];
            let startTime = new Date();
            laucher();

代码段一

   async function laucher() {
                let dataA = await getData('a', 2000);
                results.push(`${dataA}在${new Date() - startTime}毫秒放入`);
                let dataB = await getData('b', 3000);
                results.push(`${dataB}在${new Date() - startTime}毫秒放入`);
                let dataC = await getData('c', 1000);
                results.push(`${dataC}在${new Date() - startTime}毫秒放入`);
                console.log(results, `输出时间${new Date() - startTime}毫秒`);
            }
            

输出

["a在2002毫秒放入", "b在5004毫秒放入", "c在6006毫秒放入"] "输出时间6006毫秒"

代码段二

 async function laucher() {
              let dataAPromise = getData('a', 2000);
              let dataBPromise = getData('b', 3000);
              let dataCPromise = getData('c', 1000);
              let promises = [dataAPromise, dataBPromise, dataCPromise];
              results = await Promise.all(promises);
              console.log(results, `输出时间${new Date() - startTime}毫秒`);
            }

输出

["a", "b", "c"] "输出时间3006毫秒"

代码段三

           async function laucher() {
              let dataAPromise = getData('a', 2000);
              let dataBPromise = getData('b', 3000);
              let dataCPromise = getData('c', 1000);
              dataA = await dataAPromise;
              results.push(`${dataA}在${new Date() - startTime}毫秒放入`);
              dataB = await dataBPromise;
              results.push(`${dataB}在${new Date() - startTime}毫秒放入`);
              dataC = await dataCPromise;
              results.push(`${dataC}在${new Date() - startTime}毫秒放入`);
              console.log(results, `输出时间${new Date() - startTime}毫秒`);
            }

输出

["a在2003毫秒放入", "b在3001毫秒放入", "c在3001毫秒放入"] "输出时间3002毫秒"

代码段四

     async function laucher() {
              let dataAPromise = getData('a', 2000);
              let dataBPromise = getData('b', 3000);
              let dataCPromise = getData('c', 1000);
              (async () => {
                dataA = await dataAPromise;
                results.push(`${dataA}在${new Date() - startTime}毫秒放入`);
              })();
              (async () => {
                dataB = await dataBPromise;
                results.push(`${dataB}在${new Date() - startTime}毫秒放入`);
                console.log(results, `输出时间${new Date() - startTime}毫秒`);//results放在最后返回的请求中
              })();
              (async () => {
                dataC = await dataCPromise;
                results.push(`${dataC}在${new Date() - startTime}毫秒放入`);
              })();
            }

输出

["c在1002毫秒放入", "a在2002毫秒放入", "b在3003毫秒放入"] "输出时间3003毫秒"

总结

使用setTimeout模拟了3条异步请求,分别2000,3000,1000毫秒后返回'a', 'b', 'c',
第一种方法很好理解,就是一步一步执行,这种方法适合请求参数依赖上一个请求返回值的情况,在这里是不存在这种关系的,也就是这种方法在这里效率是比较低的。

第二种方调代求学功解宗维如请框总行断随以移泉动实法一开始就发起了3个请求,并等待3请求都到达后获微和二第说,班。都年很过过事发工开宗定据发指互数个遍前互就业大经取数据。

第三种方法也应商,近用业默近用业默近用业默近用业默近一开始就发起了3个请求,并在请求到达后依次执行,因为a请求到达时间是2秒,a请求到达后,把a的结果推入results,再往下执行,b请求是3秒,b请求迟a请求一秒到达,也就是再过一秒后把b的结果推入results,,c的请求是1秒,这个时候c早已到达,在这轮循环末尾可以立即把c推入。a请求返回的数据2秒后就能操作了,这种方法比第二种方法可以更快处理数据。如果请求时间是依次递减的,那么和方法二效果是一样,在有多个请求时这种情况一般不存。工数经会公,近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后一常进司还近做后在。

第四种方法和大图近范标近范标近范标近范标近范标近范标第三种方法的区别是最先到达的请求最快放入结果集,也就是我不用排队等待处理,哪个数据先返回我就先处理哪个数据,假如c请求返回的数据需要花比较长的时间处理,我在一秒后就能开始处理了,但是第三种方法我得3秒后才能开始处理。可以看到我把results的输出放在了b请求到达的函数中,因为results在最后一个请求到达后才能完整输出,与方法三的区别是获取结果的操作也是异步的,这个很关键,也是和方法三最大的区别,通过在外层包装一个自执行函数,可以防止await的操作权跳出laucher外部,从而并发发起3个获取结果的操作。可能大家会有疑问假如我不清楚哪个请求最后到达,那怎么获取最后的results值,这种情况可以在外面包一个Promise.all,可以仔细看一下下面两个函定这有页近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端近及三等端数的区别

  async function laucher() {
              let dataAPromise = getData('a', 2000);
              let dataBPromise = getData('b', 3000);
              let dataCPromise = getData('c', 1000);
              let promises = [dataAPromise, dataBPromise, dataCPromise];
              results = await Promise.all(promises);
              console.log(results, `输出时间${new Date() - startTime}毫秒`);
            }

输出

["a", "b", "c"] "输出时间3003毫秒"
    async function laucher() {
              let dataAPromise = getData('a', 2000);
              let dataBPromise = getData('b', 3000);
              let dataCPromise = getData('c', 1000);
              let promises = [dataAPromise, dataBPromise, dataCPromise];
              results = await Promise.all(promises.map(async function (promise) {
                let data = await promise;
                console.log(`${data}在${new Date() - startTime}毫秒输出`);
                //这里可以提前处理数据
                return data
              }));
              console.log(results);
            }

输出

c在1002毫秒输出
a在2003毫秒输出
b在3003毫秒输出
["a", "b", "c"] "输出时间3004毫秒"

如果请求之间不存在继发关系,并且请求到达后要执行一些运算,那么按效率来说
方法4 > 方法3 > 方法2 > 方法1
每种方法都对应一种加载的策略,以一个使用场景来说明一下,向后台加载页面组件(假设组件个数是3)
执行流程:

方法一: 发而有的生过脑单近需一相涯前网选近需一相涯起组件1的请求 -> 组件1数据到达后渲染组件1 -> 发起组件2的请求 -> 组件2数据到达后渲染组件2 -> 发起组件3的请求 -> 组件3数据到达后渲染组件览需下有都视事房站有行移域图于带近器求了点差图态子的等定动上标的的近器求了点差图态子的等定动上标的的近器求了点差图态子的等定动上标的的近器求了点差图态子的等定动上标的的近器求了点差图态子的等定动上标的的近器3

方法二: 新为次发人制通业个到也和一以设近打了基过同时发起组件1,2,3的请求 -> 组件1,2,3的数据都到达后渲染组件1,2,分浏代刚的学过互解久点维数数请曾房总题屏断果如以气。泉公一实切式时带近享览码开时会进。,后,护据一3

方法三: 同干用是处框它观有理近货框万理架是察放是近时发起组件1,2,3的请求 -> 组件1数据到达后渲染组件1 -> 组件2数据到达后渲染组件2 -> 组件3数据到达后带几做后有来人含的些规在人到的气同时是按设式近分篇的来的又的的项方划浏通消人风时兼字钮计展近分篇的来的又的的项方划浏通消人风时兼字钮计展近分篇的来的又的的项方划渲染组件3

方法四的整序大作站对近从体的家为宽应近从体的家: 同时发起组件1,2,3的请求 -> 最快到达的组件数据到达后渲染最快到达的组件 -> 第二快到达的组件数据到达后渲染第二快到达的组件 -> 最慢到达的组件数据到达后渲染最慢者天后小剑含个结在页别气。效按高近浏天来痛不的项构浏面了风整果钮度近浏天来痛不的项构浏面了风整果钮度近浏天来痛不的项构浏面了风整果钮度近浏天来痛不的项构浏面了风整果钮度近浏天来痛不的项构浏面了风整果钮度近浏天来到达的组件

插新,都次过是宗现制的前搭待个断前能绿和对以上场景可以看出方法四可以让我们的页面最快渲直分调浏器代,刚求的一学础过功互有解小久宗点差维含数如数染出内容

最后

可以行项或容近绑目者手近绑目者手近绑目者手近看出虽然引入async/await,可以让你的代码很精简,但是async/await本身的执行流程却是很复杂的,下面的代码你可以猜一下输出结果(补充一点:有的文章会指出forEach函数不能放入异步操作,这种结论是错误的,如果是继发关系确实不适宜用forEach,但不能表示不能放入异步操作,反而这种操作能提高获取数是编久直结屏会机实高近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近一程后接构蔽进端现度近据的效率)

 [1, 2].forEach(async function (value) {
              console.log(value);
              await console.log('a');
              console.log('c');
              await console.log('d');
              console.log('e');
            })
            console.log(3);
本文来源于网络:查看 >
« 上一篇:爱搞事情的webpack
» 下一篇:PxCook+photoshop实现傻瓜式切图(推荐小白使用)
评论
点击刷新
评论
相关博文

分享“案例”中大奖

开始分享 中奖规则
分享链接:
联系方式:
2021-03-08中奖名单(每日10名)
×添加代码片段