当我在一个简单的Tornado应用程序中运行此处理程序并使用 // Transition definition
const FadeTransition = (index, position) => {
const inputRange = [index - 1, index, index + 1];
const opacity = position.interpolate({
inputRange,
outputRange: [0, 1, 1],
});
return {
opacity
};
};
// Transition configurator
const TransitionConfiguration = () => {
return {
screenInterpolator: (sceneProps) => {
const {position, scene} = sceneProps;
const {index, route} = scene;
return FadeTransition(index, position);
}
}
};
// Active scenes
const appScenes = {
Demo: {
screen: Demo
},
Foo: {
screen: Foo
}
};
// Basic stack navigator
import { StackNavigator } from 'react-navigation';
const AppNavigator = StackNavigator(appScenes, {
headerMode: 'none',
transitionConfig: TransitionConfiguration
});
import { NavigationActions } from 'react-navigation';
this.props.navigate({
routeName: 'Foo',
params: {
transition: 'fade'
}
})
向它发出两个请求时,它并不是并行运行的。打印出来" 1 2 3 4 5 1 2 3 4 5",当我想要打印" 1 1 2 2 3 3 4 4 5 5"。
curl
我做错了什么?
答案 0 :(得分:4)
原因是time.sleep
是阻止函数:它不允许控件返回IOLoop
,以便可以运行其他处理程序。
当然,time.sleep
通常只是这些示例中的占位符,重点是显示处理程序中的某些内容变慢时会发生什么。无论真正的代码在做什么,要实现并发阻塞代码必须用非阻塞等价物替换。这意味着以下三点之一:
找到一个兼容协程的。对于time.sleep,请改用tornado.gen.sleep:
class CoroutineSleepHandler(RequestHandler):
@gen.coroutine
def get(self):
for i in range(5):
print(i)
yield gen.sleep(1)
当此选项可用时,通常是最佳方法。有关可能有用的异步库的链接,请参阅Tornado wiki。
查找基于回调的等效内容。与第一个选项类似,基于回调的库可用于许多任务,尽管使用它们比为协同程序设计的库稍微复杂一些。这些通常与tornado.gen.Task
一起用作适配器:
class CoroutineTimeoutHandler(RequestHandler):
@gen.coroutine
def get(self):
io_loop = IOLoop.current()
for i in range(5):
print(i)
yield gen.Task(io_loop.add_timeout, io_loop.time() + 1)
同样,Tornado wiki可用于查找合适的库。
在另一个线程上运行阻止代码。当异步库不可用时,concurrent.futures.ThreadPoolExecutor
可用于在另一个线程上运行任何阻塞代码。这是一种通用解决方案,无论是否存在异步对应物,都可以用于任何阻塞函数:
executor = concurrent.futures.ThreadPoolExecutor(8)
class ThreadPoolHandler(RequestHandler):
@gen.coroutine
def get(self):
for i in range(5):
print(i)
yield executor.submit(time.sleep, 1)
有关阻止和异步功能的更多信息,请参阅Tornado用户指南的Asynchronous I/O chapter。