av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

Python異步與JavaScript原生異步有什么區(qū)別?

 眾所周知,JavaScript 是單線程的,所以瀏覽器通過 JavaScript 發(fā)起的請求是異步請求。Python 自帶的 asyncio 模塊為 Python 帶來了原生的異步能力。

為普陀等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及普陀網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站制作、成都網(wǎng)站建設(shè)、普陀網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!

在學(xué)習(xí) asyncio 時,我們應(yīng)當(dāng)正確認(rèn)識到異步代碼在 Python 中與 JavaScript 原生代碼中有什么區(qū)別,這樣才能更好地理解Python中用同步代碼寫異步程序這個邏輯。

對于異步操作,我們?nèi)绻褂萌粘I钪械睦?,可能會幫助我們理?JavaScript 原生的異步操作,但是卻有可能阻礙我們理解 Python 的異步操作。

例如:我把洗衣機(jī)打開,等待洗衣機(jī)自動運(yùn)行的這段時間,我可以去煮飯,等待飯煮好的這個過程,我可以去看書。

現(xiàn)在假設(shè)我們要請求一個網(wǎng)址:http://httpbin.org/delay/5,這個網(wǎng)址請求以后,需要等待5秒鐘才會返回結(jié)果。我們使用 jQuery來寫一段 JavaScript 代碼:

 
 
 
 
  1. function test_async(){
  2.     $.ajax({type: 'GET',
  3.             contentType: 'application/json; charset=utf-8',
  4.             url: 'http://httpbin.org/delay/5',
  5.             success: function (response) {
  6.                 console.log('5秒請求返回:', response)
  7.             }
  8.         })
  9.     var a = 1 + 1
  10.     a = a * 2
  11.     console.log(a)
  12.     $.ajax({type: 'GET',
  13.             contentType: 'application/json; charset=utf-8',
  14.             url: 'http://httpbin.org/ip',
  15.             success: function (response) {
  16.                 console.log('查詢 IP 返回:', response)
  17.             }
  18.         })
  19.     console.log('這里是代碼的末尾')
  20. }

運(yùn)行效果如下圖所示:

可以看出來,整個代碼的執(zhí)行邏輯與我們生活中的異步是一致的,首先發(fā)起了一個5秒的請求,但是程序不會卡住等待,而是繼續(xù)運(yùn)行后面的代碼,然后發(fā)起新的請求。由于新的請求返回時間短,所以新的請求很快返回并打印,最后才是打印的5秒請求的返回結(jié)果。

這就像是我們打開了洗衣機(jī)的電源,然后去淘米煮飯,米放進(jìn)了電飯鍋,打開電飯鍋電源,然后去看書,最后飯先煮好,然后衣服再洗完。

JavaScript 原生的異步請求的過程,與日常生活中的邏輯很像。所以很容易就能理解 JavaScript 的異步流程。

但是 Python 里面,異步又是另外一種情況了。

我們來寫一段代碼:

 
 
 
 
  1. import asyncio
  2. import aiohttp
  3. async def main():
  4.     async with aiohttp.ClientSession() as client:
  5.         response = await client.get('http://httpbin.org/delay/5')
  6.         result = await response.json()
  7.         print('5秒請求返回:', result)
  8.         a = 1 + 1
  9.         a = a * 2
  10.         print(a)
  11.         new_response = await client.get('http://httpbin.org/ip')
  12.         new_result = await new_response.json()
  13.         print('查詢 IP 返回:', new_result)
  14.         print('這里是代碼的末尾')
  15. asyncio.run(main())

運(yùn)行效果如下圖所示:

可以看出,程序依然是串行運(yùn)行的,根本就沒有異步痕跡。

要讓程序異步運(yùn)行,我們需要湊夠一批任務(wù)提交給 asyncio,讓它自己通過事件循環(huán)來調(diào)度這些任務(wù):

 
 
 
 
  1. import asyncio
  2. import aiohttp
  3. async def do_plus():
  4.     a = 1 + 1
  5.     a = a * 2
  6.     print(a)
  7. async def test_delay(client):
  8.     response = await client.get('http://httpbin.org/delay/5')
  9.     result = await response.json()
  10.     print('5秒請求返回:', result)
  11. async def test_ip(client):
  12.     response = await client.get('http://httpbin.org/ip')
  13.     result = await response.json()
  14.     print('查詢 IP 返回:', result)
  15. async def test_print():
  16.     print('這里是代碼的末尾')
  17. async def main():
  18.     async with aiohttp.ClientSession() as client:
  19.         tasks = [
  20.                 asyncio.create_task(test_delay(client)),
  21.                 asyncio.create_task(do_plus()),
  22.                 asyncio.create_task(test_ip(client)),
  23.                 asyncio.create_task(test_print())
  24.                 ]
  25.         await asyncio.gather(*tasks)
  26. asyncio.run(main())

運(yùn)行效果如下圖所示:

這是由于,在asyncio 里面,task是可以并行的最小單位,并且,task 要湊夠一批一起通過asyncio.gather或者asyncio.wait提交給事件循環(huán)以后,才能并行起來。

當(dāng)使用代碼asyncio.create_task(異步函數(shù)())的時候,這個異步函數(shù)實(shí)際上并沒有真正運(yùn)行,所以,在上面的代碼中:

 
 
 
 
  1. tasks = [
  2.                 asyncio.create_task(test_delay(client)),
  3.                 asyncio.create_task(do_plus()),
  4.                 asyncio.create_task(test_ip(client)),
  5.                 asyncio.create_task(test_print())
  6.                 ]

創(chuàng)建了一個包含4個task 的列表,此時這4個異步函數(shù)中的代碼都還沒有執(zhí)行。

當(dāng)再調(diào)用await asyncio.gather(*tasks)時,這4個任務(wù)被作為4個參數(shù)傳入到了 asyncio.gather函數(shù)中,于是 Python 的事件循環(huán)開始調(diào)度他們。在這些異步函數(shù)中,包含await的地方,就是在告訴 Python,await后面的這個函數(shù)可能會有 IO 等待,可以掛起等一會再來看,現(xiàn)在可以去檢查事件循環(huán)里面其他異步任務(wù)是否已經(jīng)結(jié)束等待可以運(yùn)行。而沒有 await的地方依然是串行的,例如do_plus里面的三行代碼就是按順序一次性運(yùn)行完成的。

所以,當(dāng)我們使用 Python 的 asyncio 寫異步代碼時,我們需要提前安排好異步的切換位置并包裝為異步任務(wù),然后把一批任務(wù)一次性提交給 asyncio,讓 Python 自己根據(jù)我們安排好的切換邏輯來調(diào)度這些任務(wù)。

這就像是,當(dāng)我寫 JavaScript 的時候,我親自上陣先把洗衣機(jī)電源打開,然后我再來考慮接下來要利用等待時間做什么事情。

當(dāng)我寫 Python 的時候,我需要提前把整個計劃都安排好:先打開洗衣機(jī),在等待的時間淘米煮飯,然后再看書。并把這個計劃表提交給一個專門做事情的人來執(zhí)行。

理解了這個差別,才能更好地在 Python 中使用 asyncio。

注意,本文說到的 JavaScript異步,是 JavaScript 最原始的異步邏輯?,F(xiàn)在 JavaScript 有 Promise 等等高級功能,實(shí)現(xiàn)類似于 Python 的這種異步邏輯。


本文標(biāo)題:Python異步與JavaScript原生異步有什么區(qū)別?
當(dāng)前URL:http://uogjgqi.cn/article/ccodgeo.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們在微信上24小時期待你的聲音

解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流