js async await 多個(gè)請(qǐng)求串行與并行的講解

async/await 可能會(huì)產(chǎn)生誤導(dǎo)!十厢!在我沒(méi)研究一下之前等太,本人也是一臉懵逼,什么同步蛮放,異步缩抡,串行,并行包颁。await 不就是寫異步代碼的嗎瞻想?

//噢不,我簡(jiǎn)直是SB娩嚼,我怎么會(huì)說(shuō)出 await 不就是寫異步代碼的嗎蘑险?這樣的話?

一些文章將 async/wait 與 Promise 進(jìn)行了比較岳悟,并聲稱它是 JavaScript 下一代異步編程風(fēng)格佃迄,事實(shí)上它只不過(guò)是一種語(yǔ)法糖,不會(huì)完全改變我們的編程風(fēng)格竿音。

從本質(zhì)上說(shuō)和屎,async 函數(shù)仍然是 promise。在正確使用 async 函數(shù)之前春瞬,你必須先了解 promise柴信,更糟糕的是,大多數(shù)時(shí)候你需要在使用 promises 的同時(shí)使用 async 函數(shù)宽气。

算了随常,要理解這些,先從頭復(fù)習(xí)一下吧

第一部分????:

在當(dāng)年寫ajax的時(shí)候,多個(gè)請(qǐng)求的寫法

假設(shè) setTimeout 模擬請(qǐng)求,a和b模擬請(qǐng)求返回的數(shù)據(jù)并打印,一個(gè)請(qǐng)求假設(shè)4s
function b(){
  let a = 0 ;
  setTimeout(()=>{a=4;console.log(a)},4000)
  let b = 0 ;
  setTimeout(()=>{b=5;console.log(b)},4000)
}

image.png

寫完覺(jué)得自己特牛B萄涯,兩個(gè)請(qǐng)求并行(一起執(zhí)行)绪氛,只用了4.097s
如果兩個(gè)請(qǐng)求的數(shù)據(jù)之間有依賴性,也就是b請(qǐng)求需要a請(qǐng)求返回的數(shù)據(jù)

function b(){
  let a = 0 ;
  let b = 0 ;
  setTimeout(()=>{a=4;console.log(a)
  setTimeout(()=>{b=5;console.log(b);},4000)}
  ,4000)
}

image.png

噢不,居然用了8.097 這就是串行涝影。
如果這個(gè)時(shí)候我寫了回調(diào)函數(shù)進(jìn)行枣察。單個(gè)請(qǐng)求還無(wú)所謂,多個(gè)請(qǐng)求或者多次操作就會(huì)不優(yōu)雅了.

第二部分????

無(wú)所謂,promise會(huì)出手
隨便去網(wǎng)上搜索一下promise的作用就知道promise就是解決回調(diào)地獄的
(以為多高大上呢序目,不就是優(yōu)雅的問(wèn)題嗎臂痕?)

function c(){
  new Promise((res,rej)=>{
    setTimeout(() => {
      res(1)
    }, 2000);
  }).then(v=>console.log(v))
  console.log(4);
  new Promise((res,rej)=>{
    setTimeout(() => {
      res(3)
    }, 2000);
  }).then(v=>console.log(v))
  console.log(2);
}
image.png
Promise的意思是聲明一個(gè)異步代碼去執(zhí)行,并承諾未來(lái)一段時(shí)間內(nèi)會(huì)有結(jié)果返回(resolve,reject)這個(gè)結(jié)果使用 then函數(shù)來(lái)接受并實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用

上邊的代碼也是并行執(zhí)行了兩個(gè)promise猿涨。耗時(shí) 2.087s
何為異步代碼握童?其實(shí)你看到4和2先打印了,這其實(shí)就是異步代碼的作用叛赚,在promise的同時(shí)js線程并不會(huì)阻塞澡绩。

第三部分????

但是 promise 感覺(jué)仍然不夠優(yōu)雅,無(wú)所謂,async 會(huì)出手

async function a(){
  console.log(new Date().getSeconds());
  const a = new Promise((res,rej)=>{
    setTimeout(()=>res('fffa'),4000)
  })
  const a1 = await a
  console.log(a1);
  console.log(new Date().getSeconds());
  const b = new Promise((res,rej)=>{
    setTimeout(()=>res('fffb'),4000)
  })
  const b1 = await b
  console.log(b1);
  console.log(new Date().getSeconds());
}

image.png

這里是重點(diǎn)了俺附,我們看到打印順序是按照同步代碼的結(jié)果來(lái)打印的肥卡,耗時(shí)8.098s
這就是 async/await 的作用。讓異步的代碼寫起來(lái)更像是同步的代碼一樣(目前暫時(shí)是串行的)
拋開(kāi)對(duì)async/await的認(rèn)識(shí)昙读,我們解讀這段代碼

1.分別寫了兩段異步代碼 Promise召调,他們的結(jié)果是 a,b 并且分別打印。
2.兩個(gè)異步代碼的數(shù)據(jù)沒(méi)有依賴性蛮浑。執(zhí)行耗時(shí)是8.098s是正確的。
3.前提是我們把他們看作是同步的代碼
4.程序在8秒起步只嚣,過(guò)了4秒在12秒時(shí)候打印fffa 沮稚,再過(guò)4秒就是16秒的時(shí)候打印fffb

但這其實(shí)也是很多人在使用 async/await 時(shí)可能會(huì)犯的錯(cuò)誤::

太過(guò)串行化!!!

盡管 await 可以使代碼看起來(lái)像是同步的,但實(shí)際它們?nèi)匀皇钱惒降牟嵛瑁仨毿⌒谋苊馓^(guò)串行化蕴掏。這會(huì)導(dǎo)致執(zhí)行時(shí)間是多一倍的(8s),實(shí)際應(yīng)該是4s左右
上述代碼在邏輯上看似正確的调鲸,然而盛杰,這不是完全正確的。

await a 會(huì)等待 fffa 結(jié)束并返回結(jié)果藐石。
然后 await b的部分才被調(diào)用即供。執(zhí)行的總時(shí)間用了8s!
注意于微,b部分的代碼 并不依賴于 a部分 的結(jié)果逗嫡,實(shí)際上它們可以并行調(diào)用!然而株依,用了 await驱证,兩個(gè)調(diào)用變成串行的,總的執(zhí)行時(shí)間將比并行多一倍時(shí)間

下面是正確的方式:我們把 const a1 = await a 的執(zhí)行時(shí)機(jī)放到了 兩個(gè)promise 的后邊

async function a(){
  console.log(new Date().getSeconds());
  const a = new Promise((res,rej)=>{
    setTimeout(()=>res('fffa'),4000)
  })
  console.log(new Date().getSeconds());
  const b = new Promise((res,rej)=>{
    setTimeout(()=>res('fffb'),4000)
  })
  const a1 = await a
  const b1 = await b
  console.log(a1);
  console.log(b1);
  console.log(new Date().getSeconds());
}
image.png

為什么恋腕?為什么調(diào)換了 await a 的順序就沒(méi)問(wèn)題了抹锄?

答????:

先拋出 await 的術(shù)語(yǔ)解釋:await 操作符用于等待一個(gè) [Promise]兌現(xiàn)并獲取它兌現(xiàn)之后的值
但我個(gè)人用通俗的解釋:await 有點(diǎn)像 then()/catch(),用來(lái)接受promise返回的值。
這里 await a 的時(shí)候伙单,a是promise返回的值获高。后邊的代碼我們可以想象有點(diǎn)像被then()包裹起來(lái)了,貌似await不能很好的控制后邊的代碼哪些需要同步或異步導(dǎo)致了

 const a1 = await a
  console.log(a1);
  console.log(new Date().getSeconds());
  const b = new Promise((res,rej)=>{

這段代碼 b部分的Promise 也會(huì)等待 await a 拿到結(jié)果再去執(zhí)行车份。就不小心串行
所以結(jié)果是 8s.
當(dāng)我調(diào)換了順序之后-->

 const a1 = await a
  const b1 = await b
  console.log(a1);
  console.log(b1);

這里的 兩個(gè)await 并不會(huì)妨礙到 它上邊兩個(gè)promise 的執(zhí)行谋减,就像是 第二部分的promise代碼一樣,是并行執(zhí)行的扫沼。不過(guò)這里有另一個(gè)細(xì)節(jié)!!

盡管 兩個(gè)await 不會(huì)妨礙到promise的并行執(zhí)行出爹,但是 此時(shí) await a 會(huì)等待 a返回結(jié)果,程序此時(shí)還沒(méi)走到 await b.
也就是說(shuō)
此時(shí)程序執(zhí)行不是卡在 await b缎除,而是卡在 await a,
當(dāng) fffa 被返回的時(shí)候严就,由于兩個(gè) promise 是并行執(zhí)行的!
fffa 被返回的同時(shí)器罐,await a 得到結(jié)果梢为,程序就立馬走到 await b,由于并行且時(shí)間差不大轰坊,剛好fffb也就被返回铸董,
所以 await a 和 await b 是幾乎同一時(shí)間結(jié)果被返回,但是實(shí)際開(kāi)發(fā)環(huán)境可能是 await a返回之后要等個(gè)時(shí)間 b才會(huì)被返回肴沫,
具體看服務(wù)器接口請(qǐng)求時(shí)間粟害。
然后  console.log(a1); console.log(b1); 被一起打印

這才是真正的 await 并行請(qǐng)求!
當(dāng)然也不是完全否定了 串行颤芬,假如有一個(gè)需求悲幅,b的請(qǐng)求數(shù)據(jù) 需要包含 a請(qǐng)求返回的數(shù)據(jù),那么 b 需要等待 a站蝠, 就可以用串行的寫法了

雖然有點(diǎn)啰嗦汰具,但是為了講清楚點(diǎn),我只能這么碼字菱魔,希望有人看得懂留荔,技術(shù)有限,歡迎噴我
\color{#228B22}{前端小總結(jié)豌习,不對(duì)之處存谎,歡迎大神們噴我》事。可以的話順手點(diǎn)個(gè)贊吧~~既荚!}
\color{red}{警: 禁止抄襲,轉(zhuǎn)載說(shuō)明出處 ??}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末栋艳,一起剝皮案震驚了整個(gè)濱河市恰聘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖晴叨,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凿宾,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡兼蕊,警方通過(guò)查閱死者的電腦和手機(jī)初厚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)孙技,“玉大人产禾,你說(shuō)我怎么就攤上這事∏@玻” “怎么了亚情?”我有些...
    開(kāi)封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)哈雏。 經(jīng)常有香客問(wèn)我楞件,道長(zhǎng),這世上最難降的妖魔是什么裳瘪? 我笑而不...
    開(kāi)封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任土浸,我火速辦了婚禮,結(jié)果婚禮上彭羹,老公的妹妹穿的比我還像新娘栅迄。我一直安慰自己,他們只是感情好皆怕,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著西篓,像睡著了一般愈腾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上岂津,一...
    開(kāi)封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天虱黄,我揣著相機(jī)與錄音,去河邊找鬼吮成。 笑死橱乱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粱甫。 我是一名探鬼主播泳叠,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼茶宵!你這毒婦竟也來(lái)了危纫?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎种蝶,沒(méi)想到半個(gè)月后契耿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡螃征,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年搪桂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盯滚。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡踢械,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出淌山,到底是詐尸還是另有隱情裸燎,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布泼疑,位于F島的核電站德绿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏退渗。R本人自食惡果不足惜移稳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望会油。 院中可真熱鬧个粱,春花似錦、人聲如沸翻翩。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嫂冻。三九已至胶征,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間桨仿,已是汗流浹背睛低。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留服傍,地道東北人钱雷。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吹零,于是被迫代替她去往敵國(guó)和親罩抗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容