我正在用PHP实现HTTP请求的POC。当我们以以下方式检索响应数据时,symfony http客户端工作良好:
$response1 = $httpClient->request('GET', 'https://127.0.0.1:8000/service/a');
$response2 = $httpClient->request('GET', 'https://127.0.0.1:8000/service/b');
$array1 = $response1->toArray();
$array2 = $response2->toArray();
考虑到服务A和B都需要5秒来执行,我们的客户端代码总共只需等待5秒。
现在,问题是我们通常为不同的客户端编写不同的存储库(RepositoryA,RepositoryB)。因此,在客户端代码中,我们不会对简单的HttpResponseInterface对象进行操作,而是对一些DTO进行操作。
我想利用异步http请求,同时保持存储库的分离。
简化的方法如下所示:
private function getResponse1(): Generator
{
$response1 = $this->httpClient->request('GET', 'https://127.0.0.1:8000/service/a');
return yield $response1->toArray();
}
private function getResponse2(): Generator
{
$response2 = $this->httpClient->request('GET', 'https://127.0.0.1:8000/service/b');
return yield $response2->toArray();
}
$response1 = $this->getResponse1();
$response2 = $this->getResponse2();
$array1 = $response1->current();
$array2 = $response2->current();
如果您熟悉JS,那么Generator
对象上的current()
调用有点类似于await
构造。
最后,问题是为什么这种方法不起作用?因为测量显示,有发电机的总等待时间为10秒,而没有发电机的总等待时间仅为5秒。
下面是控制台命令,可用于重现问题:https://github.com/rela589n/generator-as-promise-poc/blob/master/src/Command/TestSyncSfClientGeneratorsCommand.php
还有一个不使用生成器的代码的工作示例:https://github.com/rela589n/generator-as-promise-poc/blob/master/src/Command/TestAsyncSfHttpClientCommand.php
1条答案
按热度按时间qcbq4gxm1#
问题很可能是生成器的第一个产量是总结果:
(除了回报率有点假,现在我把它贴进去了...)
现在,生成器也在进行资源获取:
就在返回的yield前面,这意味着生成器将等待该请求完成。
第二个发电机也是如此。
因此,当您将两个请求分布在两个不同的生成器中时,您将失去并行调用它们的能力(如在彼此之后),因为您已经通过生成器实现使生成器 * 等待第一个yield**。
因此,伪造第一个产量,并与返回建设工作。
这可能是可行的,但是我仍然不清楚toArray()实际上做了什么,因为我不知道那个库。
然而,对于PHP Generator的实现,它总是完全重复,这就是为什么它不能倒带 , 需要获得第一个yield结果。
因此,第一个yield必须是来自http-client-request协议的非阻塞结果。