一、 上篇提到了用defered对象注册回调的方式,来处理异步操作,这样大家都知道,实际情况代码很难搞的。因为当业务逻辑复杂后,这边一个异步操作,我们注册一个回调,代码跳到A地方,A里面也有异步操作,注册回调,然后跳到B,自己看起来都晕,维护起来不方便,不好读也不好排错,这时候,如果有简单的方式就更好了,能提高书写效率。

  类似于tornado的gen.coroutine,我们可以用@inlineCallbacks装饰器,配合yield关键字,将代码结构变成同步的。

二、在@inlineCallbacks装饰的情况下,先看这几点:

  1. deferred对象的结果,也就是异步操作完成后的返回结果,这个返回结果正常是传递给了callback,我们通过yield deferred可以拿到

  2. 下层callback的返回值即作为上层callback的参数,直至最外层。

  

# coding:utf-8

import time

from twisted.internet import defer, reactor
from twisted.internet.defer import inlineCallbacks, returnValue class deferTester():
def __init__(self):
self.d = defer.Deferred() #模拟耗时操作
@inlineCallbacks
def work(self):
print "[%s] 模拟耗时网络IO, 等待3秒" % nowtime()
time.sleep(3)
retult = yield('haha')#非延迟对象会立即返回
print "[%s] result = "%nowtime(),retult
reactor.callLater(2, self.d.callback, retult)
self.d.addCallback(self.first_call)
self.d.addCallback(self.second_call) def first_call(self, x):
print "[%s] inner调用,接收参数 = " % nowtime(), x
return 5 #返回的值作为之后callback的参数 def second_call(self, x):
print "[%s] nest调用,接收参数 = " % nowtime(), x def stop():
reactor.stop()
print "[%s] 停止reactor"%nowtime() def nowtime():
return time.strftime('%Y-%m-%d,%X', time.localtime()) if __name__ == '__main__':
print "[%s] 开始测试 "%nowtime()
tester = deferTester()
reactor.callWhenRunning(tester.work)#reactor调用耗时任务
print "[%s] 启动reactor "%nowtime()
reactor.callLater(8, stop) #5秒后停止reactor线程
reactor.run()

  打印结果为:

[2018-10-25,18:13:13] 开始测试
[2018-10-25,18:13:13] 启动reactor
[2018-10-25,18:13:13] 模拟耗时网络IO, 等待3秒
[2018-10-25,18:13:16] result = haha
[2018-10-25,18:13:18] first_call,接收参数 = haha
[2018-10-25,18:13:18] second_call,接收参数 = 5
[2018-10-25,18:13:21] 停止reactor

  可以看出,first_call的返回值5作为second_call的入参

  我们稍微修改下测试类如下:

  

#模拟耗时操作
@inlineCallbacks
def work(self):
print "[%s] 模拟耗时网络IO, 等待3秒" % nowtime()
time.sleep(3)
retult = yield('haha')#非延迟对象会立即返回
print "[%s] result = "%nowtime(),retult
reactor.callLater(2, self.d.callback, retult)
self.d.addCallback(self.inner_work)
res = yield self.d #此时d对象调用inner_work,返回结果为5
print "[%s] res = "%nowtime(),res @inlineCallbacks
def inner_work(self, x):
print "[%s] inner调用,接收参数 = " % nowtime(), x
yield returnValue(5) #生成器中不能用return返回结果

  结果为:

[2018-10-25,18:15:05] 开始测试
[2018-10-25,18:15:05] 启动reactor
[2018-10-25,18:15:05] 模拟耗时网络IO, 等待3秒
[2018-10-25,18:15:08] result = haha
[2018-10-25,18:15:10] inner调用,接收参数 = haha
[2018-10-25,18:15:10] res = 5
[2018-10-25,18:15:13] 停止reactor

  如果用了inlineCallback, 返回的是一个生成器,此时不能用简单的return,twisted有returnValue可以使用

(二)inlineCallbacks,同步方式写异步代码的更多相关文章

  1. boost::ASIO的同步方式和异步方式

    http://blog.csdn.net/zhuky/article/details/5364574 http://blog.csdn.net/zhuky/article/details/536468 ...

  2. 使用HTTP的同步方式还是异步方式?

    同步与异步 同步:提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步: 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完 ...

  3. iOS网络编程--NSConnection的同步连接与异步连接

    // // ZFViewController.m // 0628-表单验证 // // Created by zfan on 14-6-28. // Copyright (c) 2014年 zfan. ...

  4. 无感知的用同步的代码编写方式达到异步IO的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护

    golang/goroutine 和 swoole/coroutine 协程性能测试对比 - Go语言中文网 - Golang中文社区 https://studygolang.com/articles ...

  5. [每日一题]面试官问:Async/Await 如何通过同步的方式实现异步?

    关注「松宝写代码」,精选好文,每日一题 ​时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...

  6. node.js的作用、回调、同步异步代码、事件循环

    http://www.nodeclass.com/articles/39274 一.node.js的作用 I/O的意义,(I/O是输入/输出的简写,如:键盘敲入文本,输入,屏幕上看到文本显示输出.鼠标 ...

  7. 【WP8】同步执行异步代码

    微软的StorageFile只支持异步的方式进行文件操作,我之前也封装过一个StorageHelper,但是当所有的方法都是异步的时候也带来一些问题 1.比如我们不能在构造函数调用异步代码(等待), ...

  8. 将 async/await 异步代码转换为安全的不会死锁的同步代码

    在 async/await 异步模型(即 TAP Task-based Asynchronous Pattern)出现以前,有大量的同步代码存在于代码库中,以至于这些代码全部迁移到 async/awa ...

  9. redux本来是同步的为什么它能执行异步代码(chunk)实现原理是什么 中间件的实现原理是什么

    我们用redux执行同步的时候,都是先发起一个dispatch(actionCreator()) 1.先在actionCreator()中生成一个action对象. 2.由dispatch方法将act ...

随机推荐

  1. MySQL——复制(Replication)

    1.复制概述 1.1.复制解决的问题数据复制技术有以下一些特点:(1)    数据分布(2)    负载平衡(load balancing)(3)    备份(4)    高可用性(high avai ...

  2. html abbr标签 语法

    html abbr标签 语法 作用:标记一个缩写 大理石平台 说明:<abbr> 标签指示简称或缩写,比如 "WWW" 或 "NATO".通过对缩写 ...

  3. new/delete和malloc/free区别与联系

    1.基本概念 malloc/free (1).函数原型及说明 void *malloc(long NumBytes): 该函数分配了NumBytes个字节,并返回了指向这块内存的指针.如果分配失败,则 ...

  4. golang rabbitmq实践 (二 实现简单的消息收发)

    1:驱动 本来打算自己写一个驱动的,后来发现github上面已经有了,那我就直接拿现成的了, 驱动采用 github.com/streadway/amqp ,直接import就可以啦! 2:excha ...

  5. ICPC — International Collegiate Programming Contest Asia Regional Contest, Yokohama, 2018–12–09 题解

    目录 注意!!此题解存在大量假算法,请各位巨佬明辨! Problem A Digits Are Not Just Characters 题面 题意 思路 代码 Problem B Arithmetic ...

  6. HTTP深入浅出http请求(转)-----http请求的过程和实现机制

    摘要:此文章大概讲明了http请求的过程和实现机制,可以作为了解,至于请求头和响应头的具体信息需要查看下一篇随笔:Http请求详解(转)----请求+响应各字段详解   HTTP(HyperText ...

  7. 地图服务 纬度、经度对应坐标轴x,y

    记下,供自己参考,中国地区的经纬度,经度大,纬度小 如上海经纬度为:(经度, 纬度)(y, x)(lon, lat) 121.48 31.22 纬度---lat----x轴 经度---lon---y轴

  8. kafka window安装与配置

    一.安装jdk1.8(此处省略) 二.安装zookeeper1. 下载安装包:http://zookeeper.apache.org/releases.html,解压到指定目录(如下) 2. 在系统变 ...

  9. easyhook源码分析三——申请钩子

    EasyHook 中申请钩子的原理介绍 函数原型 内部使用的函数,为给定的入口函数申请一个hook结构. 准备将目标函数的所有调用重定向到目标函数,但是尚未实施hook. EASYHOOK_NT_IN ...

  10. Fresnel integral菲涅尔积分的一丢丢探讨

    起因源于导师的关于回旋曲线的一点问题 其中最后得到的曲率公式中的c,s’和s定义不明确 于是开始从头从(2.1)式中的积分入手探究 维基百科中Fresnel integral的S(x)与C(x)的定义 ...