setDefer 机制
最后更新于:2022-04-02 06:29:43
# setDefer 机制
[TOC]
绝大部分协程组件,都支持了`setDefer`特性。可以将请求响应式的接口拆分为两个步骤,使用此机制可以实现先发送数据, 再并发收取响应结果。
由于大多数情况下, \[建立连接和发送数据的耗时\] 相比于 \[等待响应的耗时\] 来说可以忽略不计, 所以可以简单理解为defer模式下, 多个客户端的请求响应是并发的
以`HttpClient`为例,设置`setDefer(true)`后,发起`$http->get()`请求,将不再等待服务器返回结果,而是在`send request`之后,立即返回`true`。在此之后可以继续发起其他`HttpClient`、`MySQL`、`Redis`等请求。最后再使用`$http->recv()`接收响应内容。
相比`子协程 + Channel`的实现方式,`setDefer`更简单一些。
> 需注意的是, defer特性只支持并发收取响应结果, 正如示例代码所示, 创建连接和数据的发送, 仍是串行的
## 示例代码
~~~
set([
'worker_num' => 1,
]);
$server->on('Request', function ($request, $response) {
$tcpclient = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
$tcpclient->connect('127.0.0.1', 9501,0.5)
$tcpclient->send("hello world\n");
$redis = new Swoole\Coroutine\Redis();
$redis->connect('127.0.0.1', 6379);
$redis->setDefer();
$redis->get('key');
$mysql = new Swoole\Coroutine\MySQL();
$mysql->connect([
'host' => '127.0.0.1',
'user' => 'user',
'password' => 'pass',
'database' => 'test',
]);
$mysql->setDefer();
$mysql->query('select sleep(1)');
$httpclient = new Swoole\Coroutine\Http\Client('0.0.0.0', 9599);
$httpclient->setHeaders(['Host' => "api.mp.qq.com"]);
$httpclient->set([ 'timeout' => 1]);
$httpclient->setDefer();
$httpclient->get('/');
$tcp_res = $tcpclient->recv();
$redis_res = $redis->recv();
$mysql_res = $mysql->recv();
$http_res = $httpclient->recv();
$response->end('Test End');
});
$server->start();
~~~
* [示例代码](https://wiki.swoole.com/wiki/page/604.html#entry_h2_0)
';