jswebsocket同步等待_异步与websocket 异步与WebSockets
知识点
理解同步与异步执⾏过程
理解异步代码的回调写法与yield写法
Tornado异步
异步Web客户端AsyncHTTPClient
tornado.web.asynchronous
并⾏协程⽤法
WebSocket的使⽤
认识异步
1. 同步
我们⽤两个函数来模拟两个客户端请求,并依次进⾏处理:
#coding:utf-8
defreq_a():"""模拟请求a"""
print '开始处理请求req_a'
print '完成处理请求req_a'
defreq_b():"""模拟请求b"""
print '开始处理请求req_b'
print '完成处理请求req_b'
defmain():"""模拟tornado框架,处理两个请求"""req_a()
req_b()if __name__ == "__main__":
main()
执⾏结果:
开始处理请求req_a
完成处理请求req_a
开始处理请求req_b
完成处理请求req_b
同步是按部就班的依次执⾏,始终按照同⼀个步调执⾏,上⼀个步骤未执⾏完不会执⾏下⼀步。
想⼀想,如果在处理请求req_a时需要执⾏⼀个耗时的⼯作(如IO),其执⾏过程如何?
#coding:utf-8
importtimedeflong_io():"""模拟耗时IO操作"""
print "开始执⾏IO操作"time.sleep(5)print "完成IO操作"
return "io result"
defreq_a():print "开始处理请求req_a"ret=long_io()print "ret: %s" %retprint "完成处理请求req_a"
defreq_b():print "开始处理请求req_b"
print "完成处理请求req_b"
defmain():
req_a()
req_b()if __name__=="__main__":
main()
执⾏过程:
开始处理请求req_a
开始执⾏IO操作
完成IO操作
完成处理请求req_a
开始处理请求req_b
完成处理请求req_b
在上⾯的测试中,我们看到耗时的操作会将代码执⾏阻塞住,即req_a未处理完req_b是⽆法执⾏的。
我们怎么解决耗时操作阻塞代码执⾏?
2. 异步
对于耗时的过程,我们将其交给别⼈(如其另外⼀个线程)去执⾏,⽽我们继续往下处理,当别⼈执⾏完耗时操作后再将结果反馈给我们,这就是我们所说的异步。
我们⽤容易理解的线程机制来实现异步。
2.1 回调写法实现原理
#coding:utf-8
importtimeimportthreaddeflong_io(callback):"""将耗时的操作交给另⼀线程来处理"""
def fun(cb): #回调函数作为参数
"""耗时操作"""
print "开始执⾏IO操作"time.sleep(5)print "完成IO操作,并执⾏回调函数"cb("io result") #执⾏回调函数
thread.start_new_thread(fun, (callback,)) #开启线程执⾏耗时操作
defon_finish(ret):"""回调函数"""
print "开始执⾏回调函数on_finish"
print "ret: %s" %retprint "完成执⾏回调函数on_finish"
defreq_a():print "开始处理请求req_a"long_io(on_finish)print "离开处理请求req_a"
defreq_b():print "开始处理请求req_b"time.sleep(2) #添加此句来突出显⽰程序执⾏的过程
print "完成处理请求req_b"
defmain():
req_a()
req_b()while 1: #添加此句防⽌程序退出,保证线程可以执⾏完
pass
if __name__ == '__main__':
main()
执⾏过程:
开始处理请求req_a
离开处理请求req_a
开始处理请求req_b
开始执⾏IO操作
完成处理请求req_b
完成IO操作,并执⾏回调函数
开始执⾏回调函数on_finish
ret: io result
完成执⾏回调函数on_finish
异步的特点是程序存在多个步调,即本属于同⼀个过程的代码可能在不同的步调上同时执⾏。
2.2 协程写法实现原理
在使⽤回调函数写异步程序时,需将本属于⼀个执⾏逻辑(处理请求a)的代码拆分成两个函数req_a和on_finish,这与同步程序的写法相差很⼤。⽽同步程序更便于理解业务逻辑,所以我们能否⽤同步代码的写法来编写异步程序?
回想yield关键字的作⽤?
初始版本
#coding:utf-8
importtimeimportthread
gen= None #全局⽣成器,供long_io使⽤
deflong_io():deffun():print "开始执⾏IO操作"
globalgen
time.sleep(5)try:print "完成IO操作,并send结果唤醒挂起程序继续执⾏"gen.send("io result") #使⽤send返回结果并唤醒程序继续执⾏
except StopIteration: #捕获⽣成器完成迭代,防⽌程序退出
passthread.start_new_thread(fun, ())defreq_a():print "开始处理请求req_a"ret= yieldlong_io()print "ret: %s" %retprint "完成处理请求req_a"
defreq_b():print "开始处理请求req_b"time.sleep(2)print "完成处理请求req_b"
defmain():globalgen
gen=req_a()
<()#开启⽣成器req_a的执⾏
req_b()while 1:pass
if __name__ == '__main__':
main()
执⾏过程:
开始处理请求req_a
开始处理请求req_b
开始执⾏IO操作
完成处理请求req_b
完成IO操作,并send结果唤醒挂起程序继续执⾏
ret: io result
完成处理请求req_a
升级版本
我们在上⾯编写出的版本虽然req_a的编写⽅式很类似与同步代码,但是在main中调⽤req_a的时候却不能将其简单的视为普通函数,⽽是需要作为⽣成器对待。
现在,我们试图尝试修改,让req_a与main的编写都类似与同步代码。
#coding:utf-8
importtimeimportthread
gen= None #全局⽣成器,供long_io使⽤
defgen_coroutine(f):def wrapper(*args, **kwargs):globalgen
gen=f()
<()returnwrapperdeflong_io():deffun():print "开始执⾏IO操作"
globalgen
time.sleep(5)try:print "完成IO操作,并send结果唤醒挂起程序继续执⾏"gen.send("io result") #使⽤send返回结果并唤醒程序继续执⾏
except StopIteration: #捕获⽣成器完成迭代,防⽌程序退出
passthread.start_new_thread(fun, ())
@gen_coroutinedefreq_a():print "开始处理请求req_a"ret= yieldlong_io()print "ret: %s" %retprint "完成处理请求req_a"
defreq_b():print "开始处理请求req_b"time.sleep(2)print "完成处理请求req_b"
defmain():
req_a()
req_b()while 1:pass
if __name__ == '__main__':
main()
执⾏过程:
开始处理请求req_a
开始处理请求req_b
开始执⾏IO操作
完成处理请求req_b
完成IO操作,并send结果唤醒挂起程序继续执⾏
ret: io result
完成处理请求req_a
最终版本
刚刚完成的版本依然不理想,因为存在⼀个全局变量gen来供long_io使⽤。我们现在再次改写程序,消除全局变量gen。
#coding:utf-8
importtimeimportthreaddefgen_coroutine(f):def wrapper(*args, **kwargs):
gen_f= f() #gen_f为⽣成器req_a
r = () #r为⽣成器long_io
deffun(g):
ret= g.next() #执⾏⽣成器long_io
try:
gen_f.send(ret)#将结果返回给req_a并使其继续执⾏
exceptStopIteration:passthread.start_new_thread(fun, (r,))returnwrapperdeflong_io():print "开始执⾏IO操作"time.sleep(5)print "完成IO操作,yield回操作结果"
yield "io result"@gen_coroutinedefreq_a():print "开始处理请求req_a"ret= yieldlong_io()print "ret: %s" %retprint "完成处理请求req_a"
defreq_b():print "开始处理请求req_b"time.sleep(2)print "完成处理请求req_b"
defmain():
req_a()
req_b()while 1:pass
if __name__ == '__main__':
main()
执⾏过程:
开始处理请求req_a
开始处理请求req_b
开始执⾏IO操作
await和async使用方法完成处理请求req_b
完成IO操作,yield回操作结果
ret: io result
完成处理请求req_a
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论