Python3中的Futures与ES6中的Promise之间的差异

时间:2017-11-26 05:31:27

标签: javascript python promise future python-asyncio

自Python 3.5以来,关键字(v.create as IStartCreate3)([])await被引入该语言。现在,我更像是一个Python 2.7人,而且我已经在相当一段时间内避免使用Python 3了,所以async对我来说是个新手。根据我的理解,似乎asyncio与它们在ES6(或JavaScript,ES2015中的工作方式)中的工作方式非常相似,但是您想要称之为。

这是我用来比较它们的两个脚本。

await/async
import asyncio

async def countdown(n):
    while n > 0:
        print(n)
        n -= 1
        await asyncio.sleep(1)

async def main():
    """Main, executed in an event loop"""

    # Creates two countdowns
    futures = asyncio.gather(
        countdown(3), 
        countdown(2)
    )
    # Wait for all of them to finish
    await futures
    # Exit the app
    loop.stop()

loop = asyncio.get_event_loop()
asyncio.ensure_future(main())
loop.run_forever()

有一点需要注意的是,代码非常相似,它们的工作方式基本相同。

以下是问题:

  1. 在Python和ES6中,function sleep(n){ // ES6 does not provide native sleep method with promise support return new Promise(res => setTimeout(res, n * 1000)); } async function countdown(n){ while(n > 0){ console.log(n); n -= 1; await sleep(1); } } async function main(){ // Creates two promises var promises = Promise.all([ countdown(3), countdown(2) ]); // Wait for all of them to finish await promises; // Cannot stop interpreter's event loop } main(); 都基于生成器。认为期货和Promises一样是正确的吗?

  2. 我看过await/async文档中使用的TaskFutureCoroutine这两个词。它们之间有什么区别?

  3. 我应该开始编写总是运行事件循环的Python代码吗?

2 个答案:

答案 0 :(得分:19)

  
      
  1. 在Python和ES6中,await/async都基于生成器。认为期货和Promises一样是正确的吗?
  2.   

不是Future,但Python Task大致相当于Javascript' Promise。请参阅下面的详细信息。

  
      
  1. 我看过Task文档中使用的FutureCoroutineasyncio这两个词。它们之间有什么区别?
  2.   

他们的概念完全不同。主要是,TaskFutureCoroutine组成。让我们简要描述一下这些原语(我将简化许多事情来描述主要原则):

<强>未来

未来只是一种价值的抽象,可能尚未计算并最终可用。它是一个只做一件事的简单容器 - 只要设置了值,就会触发所有已注册的回调。

如果要获取该值,请通过add_done_callback()方法注册回调。

但与Promise不同,实际计算是在外部完成的 - 外部代码必须调用set_result()方法来解决未来。

<强>协程

Coroutine是与Generator非常相似的对象。

生成器通常在for循环内迭代。它产生值,并且从PEP342接受开始,它接收值。

协程通常在asyncio库深度的事件循环内迭代。一个协程产生Future个实例。当您在协程上进行迭代并产生未来时,您应该等到这个未来得到解决。在此之后,你将send未来的价值带入协程,然后你将获得另一个未来,依此类推。

await表达式几乎与yield from表达式相同,所以通过等待其他协同程序,你停止直到该协程的所有期货都已解决,并获得协程&#39 ; s返回值。 Future是一个可迭代的迭代,它的迭代器返回实际的Future - 这大致意味着await future等于yield from future等于yield future

<强>任务

任务是Future,它实际上已经开始计算并附加到事件循环。所以它的特殊类型的Future(类Task派生自类Future),它与某个事件循环相关联,并且它有一些协同程序,用作任务执行程序

任务通常由事件循环对象创建:您为循环提供协程,它创建Task对象并开始以上述方式迭代该协程。一旦协程完成,任务的未来就由协程的返回值解决。

你知道,这个任务与JS Promise非常相似 - 它封装了后台作业及其结果。

协同程序功能和异步功能

Coroutine func是一个协程工厂,就像发电机的发电机功能一样。注意Python的协同函数和Javascript的异步函数之间的区别 - JS异步函数,当被调用时,会创建一个Promise,它的内部生成器会立即开始迭代,而Python的协同程序什么都不做,直到任务就是在它上面创建的。

  
      
  1. 我应该开始编写总是运行事件循环的Python代码吗?
  2.   

如果您需要任何asyncio功能,那么您应该。事实证明,混合同步和异步代码非常困难 - 整个程序最好是异步的(但你可以通过asyncio threadpool API在不同的线程中启动同步代码块)

答案 1 :(得分:0)

Ptyhon和ES6 await / async几乎相同,除了一些细节。

  1. ES6,await / async基于Promise Python:await / async基于Futures。发电机与此无关。
  2. 阅读更多内容,您将了解... Coroutine,用于并行编程,并且有方法可以描述Coroutine作为未来的结果
  3. 在有意义时使用事件循环(事件驱动的服务器或gui)