您好,登錄后才能下訂單哦!
這篇文章主要介紹“Python異步與JavaScript原生異步有什么不同”,在日常操作中,相信很多人在Python異步與JavaScript原生異步有什么不同問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Python異步與JavaScript原生異步有什么不同”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
現(xiàn)在假設(shè)我們要請求一個網(wǎng)址:http://httpbin.org/delay/5,這個網(wǎng)址請求以后,需要等待5秒鐘才會返回結(jié)果。我們使用 jQuery來寫一段 JavaScript 代碼:
function test_async(){ $.ajax({type: 'GET', contentType: 'application/json; charset=utf-8', url: 'http://httpbin.org/delay/5', success: function (response) { console.log('5秒請求返回:', response) } }) var a = 1 + 1 a = a * 2 console.log(a) $.ajax({type: 'GET', contentType: 'application/json; charset=utf-8', url: 'http://httpbin.org/ip', success: function (response) { console.log('查詢 IP 返回:', response) } }) console.log('這里是代碼的末尾') }
運行效果如下圖所示:
可以看出來,整個代碼的執(zhí)行邏輯與我們生活中的異步是一致的,首先發(fā)起了一個5秒的請求,但是程序不會卡住等待,而是繼續(xù)運行后面的代碼,然后發(fā)起新的請求。由于新的請求返回時間短,所以新的請求很快返回并打印,最后才是打印的5秒請求的返回結(jié)果。
這就像是我們打開了洗衣機的電源,然后去淘米煮飯,米放進了電飯鍋,打開電飯鍋電源,然后去看書,最后飯先煮好,然后衣服再洗完。
JavaScript 原生的異步請求的過程,與日常生活中的邏輯很像。所以很容易就能理解 JavaScript 的異步流程。
但是 Python 里面,異步又是另外一種情況了。
我們來寫一段代碼:
import asyncio import aiohttp async def main(): async with aiohttp.ClientSession() as client: response = await client.get('http://httpbin.org/delay/5') result = await response.json() print('5秒請求返回:', result) a = 1 + 1 a = a * 2 print(a) new_response = await client.get('http://httpbin.org/ip') new_result = await new_response.json() print('查詢 IP 返回:', new_result) print('這里是代碼的末尾') asyncio.run(main())
運行效果如下圖所示:
可以看出,程序依然是串行運行的,根本就沒有異步痕跡。
要讓程序異步運行,我們需要湊夠一批任務(wù)提交給 asyncio,讓它自己通過事件循環(huán)來調(diào)度這些任務(wù):
import asyncio import aiohttp async def do_plus(): a = 1 + 1 a = a * 2 print(a) async def test_delay(client): response = await client.get('http://httpbin.org/delay/5') result = await response.json() print('5秒請求返回:', result) async def test_ip(client): response = await client.get('http://httpbin.org/ip') result = await response.json() print('查詢 IP 返回:', result) async def test_print(): print('這里是代碼的末尾') async def main(): async with aiohttp.ClientSession() as client: tasks = [ asyncio.create_task(test_delay(client)), asyncio.create_task(do_plus()), asyncio.create_task(test_ip(client)), asyncio.create_task(test_print()) ] await asyncio.gather(*tasks) asyncio.run(main())
運行效果如下圖所示:
這是由于,在asyncio 里面,task是可以并行的最小單位,并且,task 要湊夠一批一起通過asyncio.gather或者asyncio.wait提交給事件循環(huán)以后,才能并行起來。
當(dāng)使用代碼asyncio.create_task(異步函數(shù)())的時候,這個異步函數(shù)實際上并沒有真正運行,所以,在上面的代碼中:
tasks = [ asyncio.create_task(test_delay(client)), asyncio.create_task(do_plus()), asyncio.create_task(test_ip(client)), asyncio.create_task(test_print()) ]
創(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é)束等待可以運行。而沒有 await的地方依然是串行的,例如do_plus里面的三行代碼就是按順序一次性運行完成的。
所以,當(dāng)我們使用 Python 的 asyncio 寫異步代碼時,我們需要提前安排好異步的切換位置并包裝為異步任務(wù),然后把一批任務(wù)一次性提交給 asyncio,讓 Python 自己根據(jù)我們安排好的切換邏輯來調(diào)度這些任務(wù)。
到此,關(guān)于“Python異步與JavaScript原生異步有什么不同”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。