先上代碼
公共代碼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毫秒"總結(jié)
使用setTimeout模擬了3條異步請求,分別2000,3000,1000毫秒后返回"a", "b", "c",
第一種方法很好理解,就是一步一步執(zhí)行,這種方法適合請求參數(shù)依賴上一個請求返回值的情況,在這里是不存在這種關(guān)系的,也就是這種方法在這里效率是比較低的。
第二種方法一開始就發(fā)起了3個請求,并等待3請求都到達后獲取數(shù)據(jù)。
第三種方法也一開始就發(fā)起了3個請求,并在請求到達后依次執(zhí)行,因為a請求到達時間是2秒,a請求到達后,把a的結(jié)果推入results,再往下執(zhí)行,b請求是3秒,b請求遲a請求一秒到達,也就是再過一秒后把b的結(jié)果推入results,,c的請求是1秒,這個時候c早已到達,在這輪循環(huán)末尾可以立即把c推入。a請求返回的數(shù)據(jù)2秒后就能操作了,這種方法比第二種方法可以更快處理數(shù)據(jù)。如果請求時間是依次遞減的,那么和方法二效果是一樣,在有多個請求時這種情況一般不存在。
第四種方法和第三種方法的區(qū)別是最先到達的請求最快放入結(jié)果集,也就是我不用排隊等待處理,哪個數(shù)據(jù)先返回我就先處理哪個數(shù)據(jù),假如c請求返回的數(shù)據(jù)需要花比較長的時間處理,我在一秒后就能開始處理了,但是第三種方法我得3秒后才能開始處理??梢钥吹轿野裷esults的輸出放在了b請求到達的函數(shù)中,因為results在最后一個請求到達后才能完整輸出,與方法三的區(qū)別是獲取結(jié)果的操作也是異步的,這個很關(guān)鍵,也是和方法三最大的區(qū)別,通過在外層包裝一個自執(zhí)行函數(shù),可以防止await的操作權(quán)跳出laucher外部,從而并發(fā)發(fā)起3個獲取結(jié)果的操作。可能大家會有疑問假如我不清楚哪個請求最后到達,那怎么獲取最后的results值,這種情況可以在外面包一個Promise.all,可以仔細看一下下面兩個函數(shù)的區(qū)別
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}毫秒輸出`); //這里可以提前處理數(shù)據(jù) return data })); console.log(results); }
輸出
c在1002毫秒輸出 a在2003毫秒輸出 b在3003毫秒輸出 ["a", "b", "c"] "輸出時間3004毫秒"
如果請求之間不存在繼發(fā)關(guān)系,并且請求到達后要執(zhí)行一些運算,那么按效率來說
方法4 > 方法3 > 方法2 > 方法1
每種方法都對應(yīng)一種加載的策略,以一個使用場景來說明一下,向后臺加載頁面組件(假設(shè)組件個數(shù)是3)
執(zhí)行流程:
方法一: 發(fā)起組件1的請求 -> 組件1數(shù)據(jù)到達后渲染組件1 -> 發(fā)起組件2的請求 -> 組件2數(shù)據(jù)到達后渲染組件2 -> 發(fā)起組件3的請求 -> 組件3數(shù)據(jù)到達后渲染組件3
方法二: 同時發(fā)起組件1,2,3的請求 -> 組件1,2,3的數(shù)據(jù)都到達后渲染組件1,2,3
方法三: 同時發(fā)起組件1,2,3的請求 -> 組件1數(shù)據(jù)到達后渲染組件1 -> 組件2數(shù)據(jù)到達后渲染組件2 -> 組件3數(shù)據(jù)到達后渲染組件3
方法四: 同時發(fā)起組件1,2,3的請求 -> 最快到達的組件數(shù)據(jù)到達后渲染最快到達的組件 -> 第二快到達的組件數(shù)據(jù)到達后渲染第二快到達的組件 -> 最慢到達的組件數(shù)據(jù)到達后渲染最慢到達的組件
針對以上場景可以看出方法四可以讓我們的頁面最快渲染出內(nèi)容
最后可以看出雖然引入async/await,可以讓你的代碼很精簡,但是async/await本身的執(zhí)行流程卻是很復(fù)雜的,下面的代碼你可以猜一下輸出結(jié)果(補充一點:有的文章會指出forEach函數(shù)不能放入異步操作,這種結(jié)論是錯誤的,如果是繼發(fā)關(guān)系確實不適宜用forEach,但不能表示不能放入異步操作,反而這種操作能提高獲取數(shù)據(jù)的效率)
[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);
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/107479.html
摘要:第二種方法一開始就發(fā)起了個請求并等待請求都到達后獲取數(shù)據(jù)。請求返回的數(shù)據(jù)秒后就能操作了這種方法比第二種方法可以更快處理數(shù)據(jù)。如果請求時間是依次遞減的那么和方法二效果是一樣在有多個請求時這種情況一般不存在。 先上代碼 公共代碼 function getData(data, time) { return new Promise(function (resol...
摘要:第二種方法一開始就發(fā)起了個請求并等待請求都到達后獲取數(shù)據(jù)。請求返回的數(shù)據(jù)秒后就能操作了這種方法比第二種方法可以更快處理數(shù)據(jù)。如果請求時間是依次遞減的那么和方法二效果是一樣在有多個請求時這種情況一般不存在。 先上代碼 公共代碼 function getData(data, time) { return new Promise(function (resol...
摘要:以往的異步方法無外乎回調(diào)函數(shù)和。當然,對這個新特性也有一定的擔心,體現(xiàn)在他使得異步代碼變的不再明顯,我們好不容易已經(jīng)學(xué)會并習(xí)慣了使用回調(diào)函數(shù)或者來處理異步。 自從Node的7.6版本,已經(jīng)默認支持async/await特性了。如果你還沒有使用過他,或者對他的用法不太了解,這篇文章會告訴你為什么這個特性不容錯過。本文輔以大量實例,相信你能很輕松的看懂,并了解Javascript處理異步的...
摘要:以往的異步方法無外乎回調(diào)函數(shù)和。當然,對這個新特性也有一定的擔心,體現(xiàn)在他使得異步代碼變的不再明顯,我們好不容易已經(jīng)學(xué)會并習(xí)慣了使用回調(diào)函數(shù)或者來處理異步。 自從Node的7.6版本,已經(jīng)默認支持async/await特性了。如果你還沒有使用過他,或者對他的用法不太了解,這篇文章會告訴你為什么這個特性不容錯過。本文輔以大量實例,相信你能很輕松的看懂,并了解Javascript處理異步的...
閱讀 1413·2021-10-14 09:43
閱讀 1006·2021-09-10 10:51
閱讀 1457·2021-09-01 10:42
閱讀 2200·2019-08-30 15:55
閱讀 595·2019-08-30 15:55
閱讀 2355·2019-08-30 14:21
閱讀 1728·2019-08-30 13:04
閱讀 3478·2019-08-29 13:09