第一段代码publiccodefunctiongetData(data,time){returnnewPromise(function(resolve,reject){setTimeout(function(){resolve(data);},时间)})}让结果=[];让startTime=newDate();劳歇尔();代码段asyncfunctionlaucher(){letdataA=awaitgetData('a',2000);results.push(`${dataA}in${newDate()-startTime}毫秒`);让dataB=awaitgetData('b',3000);results.push(`${dataB}in${newDate()-startTime}毫秒进入`);让dataC=awaitgetData('c',1000);results.push(`${dataC}到${newDate()-startTime}毫秒`);console.log(results,`输出时间${newDate()-startTime}毫秒`);}output["a投入2002毫秒","b投入5004毫秒","c投入6006毫秒"]"输出时间6006毫秒"代码段2asyncfunctionlaucher(){让dataAPromise=getData('a',2000);让dataBPromise=getData('b',3000);让dataCPromise=getData('c',1000);让promises=[dataAPromise,dataBPromise,dataCPromise];结果=awaitPromise.all(promises);console.log(results,`输出时间${newDate()-startTime}毫秒`);}Output["a","b","c"]"Outputtime3006milliseconds"代码段3asyncfunctionlaucher(){letdataAPromise=getData('a',2000);让dataBPromise=getData('b',3000);让dataCPromise=getData('c',1000);dataA=等待dataAPromise;results.push(`${dataA}放入${newDate()-startTime}毫秒`);dataB=等待dataBPromise;results.push(`${dataB}in${newDate()-startTime}毫秒放置`);dataC=等待dataCPromise;results.push(`${dataC}put`in${newDate()-startTime}毫秒);console.log(results,`输出时间${newDate())-startTime}毫秒`);}output["aputin2003milliseconds","bputin3001milliseconds","cputin3001milliseconds"]"outputtime3002milliseconds"codesegment4asyncfunctionlaucher(){letdataAPromise=getData('a',2000);让dataBPromise=getData('b',3000);让dataCPromise=getData('c',1000);(async()=>{dataA=awaitdataAPromise;results.push(`${dataA}以毫秒为单位从${newDate()-startTime}`);})();(async()=>{dataB=awaitdataBPromise;results.push(`${dataB}put`in${newDate()-startTime}毫秒;console.log(results,`输出时间${newDate()-startTime}milliseconds`);//results放在最后返回的请求中Date()-startTime}`);})();}output["c放在1002毫秒","a放在2002毫秒","b放在3003毫秒"]"输出时间3003毫秒"总结使用setTimeout模拟3次异步请求,分别为20在00、3000和1000毫秒后返回'a'、'b'、'c'。第一种方法很容易理解,就是一步步执行。该方法适用于请求参数依赖于上一次请求的返回值的情况。这里没有这种关系,也就是这种方法在这里效率比较低。第二种方法一开始就发起了3个请求,等待3个请求都到达之后获取数据。第三种方法一开始也是发起3个请求,请求到达后依次执行,因为一个请求到达时间为2秒,a请求到达后,将a的结果压入results,然后执行down,b请求3秒,b请求比a请求晚一秒到达,也就是b的结果再过一秒后push到results中,c的请求是1秒,此时c已经到了,这一轮循环结束可以马上Pushc进去。一个request返回的数据2秒后就可以操作了。这种方法可以比第二种方法更快地处理数据。如果请求时间是按顺序递减的,效果和方法2是一样的,这种情况在有多个请求的时候一般不存在。第四种方法和第三种方法的区别在于先到达的请求最快放入结果集中,也就是我不需要排队等待处理,先处理哪些数据先返回.如果crequest返回的数据需要处理很长时间,我一秒后才开始处理,但是第三种方法我得3秒后才开始处理。可以看到我把结果的输出放在了b请求到达的函数中,因为只有最后一个请求到达后才能完整的输出结果。与第三种方法不同的是获取结果的操作也是异步的。这个很重要,也和方法三最大的区别在于,通过在外层包裹一个自执行函数,可以防止await的操作权跳出laucher,从而启动三个并发获取结果的操作。您可能有疑问。如果不知道最后到达的是哪个请求,如何得到最终的results值。在这种情况下,您可以在外面包装一个Promise.all。你可以仔细看看下面两个函数的区别asyncfunctionlaucher(){letdataAPromise=getData('a',2000);让dataBPromise=getData('b',3000);让dataCPromise=getData('c',1000);让promises=[dataAPromise,dataBPromise,dataCPromise];结果=等待承诺.all(承诺);console.log(results,`输出时间${newDate()-startTime}毫秒`);}Output["a","b","c"]"输出时间3003毫秒"asyncfunctionlaucher(){letdataAPromise=getData('a',2000);让dataBPromise=getData('b',3000);让dataCPromise=getData('c',1000);让promises=[dataAPromise,dataBPromise,dataCPromise];results=awaitPromise.all(promises.map(asyncfunction(promise){letdata=awaitpromise;console.log(`${data}从${newDate()-startTime}开始以毫秒为单位输出);//这里的数据可以提前处理返回数据}));控制台日志(结果);}在1002毫秒输出c在2003毫秒输出a在3003毫秒输出b["a","b","c"]"输出时间3004毫秒"如果请求之间没有后续关系,需要进行一些计算请求到达后执行,那么从效率上来说,方法4>方法3>方法2>方法1每个方法对应一个加载的Strategy,用一个使用场景来说明,加载页面组件到后台(假设组件数量是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同时出现->在最快到达的组件数据到达后渲染最快到达的组件->在其数据到达后渲染第二快到达的组件->最慢到达的组件在数据到达后渲染最慢到达的组件到达。基于上面的场景,我们可以看到方法4可以让我们的页面以最快的速度呈现内容。最后我们可以看到,虽然引入async/await可以让你的代码非常简洁,但是async/await本身的执行过程是非常复杂的。可以猜想下面代码的输出结果(补充一点:有些文章会指出forEach函数不能放入异步操作,这个结论是错误的,如果是次要关系,确实不适合用forEach,但并不是说不能放入异步操作,只是这个操作可以提高数据获取的效率)[1,2].forEach(asyncfunction(value){console.log(value);awaitconsole.log('a');console.log('c');等待console.log('d');console.log('e');})console.log(3);
