当前位置: 首页 » 综合知识 » it知识 » 正文

Python异步与JavaScript原生异步有什么不同

发布时间:2023-07-30 以下文章来源于网友投稿,内容仅供参考!

现在假设我们要请求一个网址:httpbin.org/delay/5,这个网址请求以后,需要等待5秒钟才会返回结果。我们使用  jQuery来写一段 JavaScript 代码:

function test_async(){     $.ajax({type: 'GET',             contentType: 'application/json; charset=utf-8',             url: '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: 'httpbin.org/ip',             success: function (response) {                 console.log('查询 IP 返回:', response)              }         })     console.log('这里是代码的末尾') }

运行效果如下图所示:

可以看出来,整个代码的执行逻辑与我们生活中的异步是一致的,首先发起了一个5秒的请求,但是程序不会卡住等待,而是继续运行后面的代码,然后发起新的请求。由于新的请求返回时间短,所以新的请求很快返回并打印,最后才是打印的5秒请求的返回结果。

这就像是我们打开了洗衣机的电源,然后去淘米煮饭,米放进了电饭锅,打开电饭锅电源,然后去看书,最后饭先煮好,然后衣服再洗完。

JavaScript 原生的异步请求的过程,与日常生活中的逻辑很像。所以很容易就能理解 JavaScript 的异步流程。

但是 Python 里面,异步又是另外一种情况了。

我们来写一段代码:

import asyncio import aiohttp  async def main():     async with aiohttp.ClientSession() as client:         response = await client.get('httpbin.org/delay/5')         result = await response.json()         print('5秒请求返回:', result)         a = 1 + 1         a = a * 2         print(a)         new_response = await client.get('httpbin.org/ip')         new_result = await new_response.json()         print('查询 IP 返回:', new_result)         print('这里是代码的末尾')  asyncio.run(main())

运行效果如下图所示:

可以看出,程序依然是串行运行的,根本就没有异步痕迹。

要让程序异步运行,我们需要凑够一批任务提交给 asyncio,让它自己通过事件循环来调度这些任务:

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('httpbin.org/delay/5')     result = await response.json()     print('5秒请求返回:', result)   async def test_ip(client):     response = await client.get('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提交给事件循环以后,才能并行起来。

当使用代码asyncio.create_task(异步函数())的时候,这个异步函数实际上并没有真正运行,所以,在上面的代码中:

tasks = [                 asyncio.create_task(test_delay(client)),                 asyncio.create_task(do_plus()),                 asyncio.create_task(test_ip(client)),                 asyncio.create_task(test_print())                 ]

创建了一个包含4个task 的列表,此时这4个异步函数中的代码都还没有执行。

当再调用await asyncio.gather(*tasks)时,这4个任务被作为4个参数传入到了 asyncio.gather函数中,于是  Python 的事件循环开始调度他们。在这些异步函数中,包含await的地方,就是在告诉 Python,await后面的这个函数可能会有 IO  等待,可以挂起等一会再来看,现在可以去检查事件循环里面其他异步任务是否已经结束等待可以运行。而没有  await的地方依然是串行的,例如do_plus里面的三行代码就是按顺序一次性运行完成的。

所以,当我们使用 Python 的 asyncio 写异步代码时,我们需要提前安排好异步的切换位置并包装为异步任务,然后把一批任务一次性提交给  asyncio,让 Python 自己根据我们安排好的切换逻辑来调度这些任务。

  • • Linux Ecdsa密钥长度选择有何依据

    在Linux

  • • Linux Khook在内核监控中的应用如何

    Linux

  • • Linux Gsoap是否支持异步通信

    GSOAP是

  • • Linux Coremail如何提升用户体验

    提升Linu

  • • Linux Ecdsa算法有哪些局限性

    ECDSA

  • 哎呀音乐钢琴键盘学习《 钢琴主人训练营》 西瓜学琴
    郭蝈 陪练钢琴 30节课时 考级刚需 让孩子每一次练琴都是高质量的
    30天轻松学会五线谱 流行钢琴自学初级教程 牙牙学琴
    流行爵士钢琴实战技巧VIP课 - 继伟 哎呀音乐
    【海上钢琴师】原版 MT1990钢琴谱
    百首经典流行钢琴实战曲集 - 继伟
    雷费尔德电钢琴重锤88键专业考级儿童初学者数码电子钢琴家用
    小练咖 真人钢琴陪练 1v1服务 2999随时退 1课时50分钟 考级刚需
    雅马哈电钢琴88键重锤CLP735智能数码电子钢琴家用专业初学者考级
    【原装进口】Yamaha/雅马哈钢琴 b121 SC2原声静音钢琴
  • 珠海专业调钢琴
  • 天津宝坻区调钢琴
  • 天津静海区钢琴调音
  • 成都简阳市钢琴调律
  • 大连瓦房店市钢琴调音
  • 眉山调钢琴联系方式
  • 惠州大亚湾钢琴调琴师
  • 长治调琴师
  • 厦门湖里区钢琴调音师
  • 上海普陀区钢琴调音师