javascript - Python3 中的 Futures 和 ES6 中的 Promises 的区别

标签 javascript python promise future python-asyncio

自 Python 3.5 起,关键字 awaitasync 被引入该语言。现在,我更像是一个 Python 2.7 的人,而且我已经有一段时间避免使用 Python 3,所以 asyncio 对我来说很陌生。据我了解,await/async 的工作方式似乎与它们在 ES6(或 JavaScript、ES2015,无论您如何调用它)中的工作方式非常相似。

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

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()
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();

需要注意的一件事是代码非常相似,而且它们的工作方式几乎相同。

问题如下:

  1. 在 Python 和 ES6 中,await/async 都是基于生成器的。认为 Future 与 Promises 相同是否正确?

  2. 我在asyncio 文档中看到了术语TaskFutureCoroutine。它们之间有什么区别?

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

最佳答案

  1. In both Python and ES6, await/async are based on generators. Is it a correct to think Futures are the same as Promises?

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

  1. I have seen the terms Task, Future and Coroutine used in the asyncio documentation. What are the differences between them?

它们是完全不同的概念。 Task主要由FutureCoroutine组成。让我们简要描述一下这些原语(我将简化很多事情以仅描述主要原理):

future

Future 只是对值的抽象,可能尚未计算但最终可用。这是一个只做一件事的简单容器 - 每当设置值时,触发所有已注册的回调。

如果您想获得该值,您可以通过 add_done_callback() 方法注册一个回调。

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

协程

Coroutine 是非常类似于Generator 的对象。

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

协程通常在 asyncio 库的深处的事件循环中迭代。协程产生 Future 实例。当你迭代一个协程并产生一个 future 时,你应该等到这个 future 被解决。之后,您应将 future 的值发送到协程中,然后您将收到另一个 future,依此类推。

await 表达式实际上与 yield from 表达式相同,因此通过等待 其他协程,您可以停止,直到该协程拥有所有 future resolved,得到协程的返回值。 Future 是一次可迭代的,它的迭代器返回实际的 Future - 这大致意味着 await future 等于 yield from future 等于 yield future

任务

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

任务通常由事件循环对象创建:你给循环一个协程,它创建任务对象并开始以上述方式迭代该协程。协程完成后,Task 的 Future 由协程的返回值解决。

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

协程函数和异步函数

Coroutine func 是一个协程工厂,就像生成器函数之于生成器。请注意 Python 的协程函数和 Javascript 的异步函数之间的区别 - JS 异步函数在被调用时会创建一个 Promise 并且其内部生成器会立即开始迭代,而 Python 的协程什么都不做,直到在其上创建任务。

  1. Should I start writing Python code that always has an event loop running?

如果您需要任何 asyncio 功能,那么您应该这样做。事实证明,很难混契约(Contract)步和异步代码——你的整个程序最好是异步的(但你可以通过 asyncio 线程池 API 在单独的线程中启动同步代码块)

关于javascript - Python3 中的 Futures 和 ES6 中的 Promises 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47493369/

相关文章:

python - 如何在 Python 中使用二级代理设置?

ios - 来自 CNContactStore 请求访问的错误 "A promise was finished incorrectly"

javascript - 是否可以从内部 Promise 获取父函数的回调?

javascript - 将基于鼠标移动设置 div 样式的函数从 jQuery 转换为 Angular 会使坐标变得困惑

javascript - simplePagination jQuery 服务器端

python - 检查sqlalchemy中的sqlite连接错误

javascript - Promises.all 的快速失败行为

javascript - 当文本框填充 Angular js中的数据时禁用跨度

javascript - Math.random避免相同的结果,如何防止代码忽略条件语句?

python - 将 pandas 条目连接到单个列列表中