python的asyncio模组(六):Future对象与Task对象(二)

前言

这篇文章需要对javascript的promise有基本的认识,对不熟的读者可能不太友善,需要自行google,请大家海涵orz

这一次的教学我们接续上一篇python的asyncio模组(五):Future对象与Task对象的内容。

在上一篇结尾我们用了Future对象去模拟javascript的promise物件的行为,但还没有解释程式的实际内容,所以就留到这次的教学做解说。

接续上一篇内容

程式我就不贴了,我觉得放在分页或是放在另一个视窗一起看比较方便。

先把重点放在最末尾的几行:

loop = asyncio.get_event_loop()success_future = loop.create_future()fail_future = loop.create_future()

不像javascript本身内置Event loop,python必须明确的定义出一个Event loop来实行异步程式。

然后我们用loop.create_future创了两个Future物件,success_future和fail_future,另外要注意一件事,因为Future本身就是用来执行异步程式的,所以在初始化时,就会绑定一个Event loop,也就是Future裏面会有一个内置成员self._loop,也就是我们刚刚创立的loop变数。

success_future.add_done_callback(success_callback)fail_future.add_done_callback(fail_callback)

我们让两个Future物件各自增加一个callback,当我们执行future.set_result()和future.set_exception()的时候(也就是上一篇说的当我们指定了任务的结果),这些callback就会自动执行。

之所以能够自动执行callback就是因为Future在set_result()或是set_exception()之后会驱动内置成员self._loop去执行先前加入的callback。

loop.call_soon(promise_example, 'success', success_future)loop.call_soon(promise_example, 'fail', fail_future)loop.run_until_complete(asyncio.wait([success_future, fail_future]))

之前的文章python的asyncio模组(四):Event loop常用API似乎没有提到call_soon的用法,那是因为call_soon是比较底层的用法,在asyncio的一般应用情境下,是不会使用到call_soon,也不会真的操作Future对象,但以教学的目的来说,稍微了解这些底层的运作也是重要的。

call_soon(func, *args)会指定一个要执行的function和要放进func的参数,当启动Event loop时就会直接执行被放入call_soon的func。

最后一行的用法在python的asyncio模组(三):建立Event Loop和定义协程都有提到:

run_until_complete指定某个任务完成就会停止Event loop,可以传入coroutine或Task或Future。asyncio.wait把一个任务(可以是coroutine或Task或Future)清单组成一个大的任务。
所以最后一行指的是如果success_future和fail_future都已经被指定任务的结果且执行完各自的callback就会停止Event loop。

接下来我们来把上篇文章的javascript程式和python程式做一个功能上的比对,这样我们就更能了解我们的Future是如何模拟出promise的功能。

1. Future物件相当于js的promise物件

js程式里的success_promise和fail_promise相当于python程式里的success_future和fail_future,虽然结构上有点不一样,比如说js的promise一开始就直接包住一个function,而Future只是作为一个参数互相传递。

但是他们扮演的角色都是差不多的,他们得到了一个结果后就会呼叫对应的callback,像下面第四点和第五点所说的。

2. future._loop.call_later相当于js里的setTimeout

js程式里的setTimeout会提醒其内置的Event loop在1000毫秒之后执行setTimeout裏面的callback,而python程式的future则会呼叫其内部变数_loop的一个方法call_later说,在1秒后呼叫setTimeout_func,这是一样的概念。

call_later也跟call_soon一样,是比较底层的用法,顾名思义,call_later就是在经过一定时间后才会呼叫某个function。

3. setTimeout_func相当于js中setTimeout里面放进去的callback

4. future.set_result()相当于js promise里面的resolve()

5. future.set_exception()相当于js promise里面的reject()

js程式中setTimeout里面的callback根据success_or_fail的值来决定呼叫resolve('success')或是reject(new Error('fail')),这就跟python程式中的setTimeout_func,根据success_or_fail的值来决定呼叫future.set_result('success')或是future.set_exception(Exception('fail'))。

6. success_callback融合了js程式里的success_promise.then和success_promise.catch

7. fail_callback融合了js程式里的fail_promise.then和fail_promise.catch

归功于刚刚解说的:

success_future.add_done_callback(success_callback)fail_future.add_done_callback(fail_callback)

success_future只要被指定结果(set_result或是set_exception)就会呼叫success_callback。
fail_future只要被指定结果(set_result或是set_exception)就会呼叫fail_callback。

然而success_callback和fail_callback全都同时包办js程式中的then和catch,之所以能同时融合两种功能是因为success_callback和fail_callback裏面都做了try/catch的处理。

结尾

不知道这次文章会写这么长,还没讲到Task感觉就已经到了一个篇幅的量。

会啰哩叭唆这么多,主要还是想好好解释Future如何在底层实现异步执行,希望大家能看懂。

下一次的教学会讲解使用Coroutin和Task对象后如何改善异步程式的可读性,然后我们会发现一件很重要的事情,Javascript为了改善异步程式的可读性,从ES6的Promise推进到ES7的async/await,这与Future对象的使用进展到Task对象的使用是类似的概念。

下一篇教学:
python的asyncio模组(七):Future对象与Task对象(三)


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章