使用 php 的异步 http 调用
Async http call with php
我有一个循环,它要从文件中读取数据块,将这些块发送到 rest api,然后继续直到 EOF,但我希望这个在循环内是异步的,所以,我不必等到 API 响应读取下一个块。
我一直在研究 Amphp 和 ReactPHP,因为找不到解决方案,或者我不明白应该如何使用这些库。
这是我正在做的伪造。
<?php
while($file.read()){
$chunk = getNextChunk();
sendChunkAsync($chunk);
}
function getNextChunk(){
echo "reading next chunk";
// read next chunk of data
}
带有 amphp 的示例
function sendChunkAsync($chunk){
Loop::run(function () {
$uri = "https://testapi.com/api";
$client = new DefaultClient;
try {
$promises = $client->request($uri);
$responses = yield $promises;
echo "chunk processed";
} catch (Amp\Artax\HttpException $error) {
// log error
// $error->getMessage() . PHP_EOL;
}
});
}
在这种情况下,我希望(如果读取块比从 api 获得响应更快)是这样的,不要相信这个文学,我正在尝试为您说明。
正在读取下一个块
正在读取下一个块
块已处理
正在读取下一个块
块已处理
块已处理
我打算使用 React,因为我更了解这个库,但它们的工作方式相似。
编辑:已更新,请参阅评论
这将读入一个文件,每次收到一大块数据时,它都会创建一个 api 调用并发送数据
<?php
require_once __DIR__ . '/vendor/autoload.php';
function async_send($config, $file, callable $proccessor)
{
$config['ssl'] = true === $config['ssl'] ? 's' : '';
$client = new \GuzzleHttp\Client([
'base_uri' => 'http' . $config['ssl'] . '://' . $config['domain'] . '/rest/all/V1/',
'verify' => false,
'http_errors' => false
]);
$loop = \React\EventLoop\Factory::create();
$filesystem = \React\Filesystem\Filesystem::create($loop);
$filesystem->getContents($file)->then(function($contents) use ($config, $proccessor, $client) {
$contents = $proccessor($contents);
$client->post($config['uri'], ['body' => $contents]);
});
}
$config = [
'domain' => 'example.com',
'ssl' => true
];
//somewhere later
$configp['uri'] = 'products';
async_send($configp, __DIR__ . 'my.csv', function ($contents) {
return json_encode($contents);
});
以防其他人正在尝试解决类似问题
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use React\HttpClient\Client as ReactClient;
function async_send($loop, $filePath, callable $proccessor)
{
echo "starting";
echo "\n\r";
try {
$filesystem = \React\Filesystem\Filesystem::create($loop);
$file = $filesystem->file($filePath);
$file->open('r')
->then(function ($stream) use ($loop, $proccessor){
$stream->on('data', function ($chunk) use ($loop, $proccessor) {
$proccessor($chunk);
});
});
} catch (\Exception $e) {
echo "failed";
echo "\n\r";
}
echo "ending reading";
echo "\n\r";
}
function callApiReal($loop, $fileChunk = null)
{
echo "ready to call api". PHP_EOL;
$uri = "https://testapi.com/";
try {
$client = new ReactClient($loop);
} catch (\Exception $e) {
echo "Error";
}
echo "ready to call api";
$request = $client->request('POST', $uri, $fileChunk);
$request->on('response', function ($response) use ($uri) {
$response->on('data', function ($data_chunk) {
echo 'data chunk from api received';
echo "\n\r";
});
// subscribe to listen to the end of the response
$response->on('end', function () use ($uri) {
echo "operation has completed";
echo "\n\r";
});
});
$request->on('error', function ($error) {
// something went bad in the request
echo "Damm!";
echo "\n\r";
});
$request->end();
}
// main loop
$loop = React\EventLoop\Factory::create();
//somewhere later
async_send($loop, __DIR__ . '/my.csv', function ($chunk) use ($loop) {
echo "calling api";
callApiReal($loop, $chunk);
echo "\n\r";
});
$loop->run();
我有一个循环,它要从文件中读取数据块,将这些块发送到 rest api,然后继续直到 EOF,但我希望这个在循环内是异步的,所以,我不必等到 API 响应读取下一个块。 我一直在研究 Amphp 和 ReactPHP,因为找不到解决方案,或者我不明白应该如何使用这些库。 这是我正在做的伪造。
<?php
while($file.read()){
$chunk = getNextChunk();
sendChunkAsync($chunk);
}
function getNextChunk(){
echo "reading next chunk";
// read next chunk of data
}
带有 amphp 的示例
function sendChunkAsync($chunk){
Loop::run(function () {
$uri = "https://testapi.com/api";
$client = new DefaultClient;
try {
$promises = $client->request($uri);
$responses = yield $promises;
echo "chunk processed";
} catch (Amp\Artax\HttpException $error) {
// log error
// $error->getMessage() . PHP_EOL;
}
});
}
在这种情况下,我希望(如果读取块比从 api 获得响应更快)是这样的,不要相信这个文学,我正在尝试为您说明。
正在读取下一个块
正在读取下一个块
块已处理
正在读取下一个块
块已处理
块已处理
我打算使用 React,因为我更了解这个库,但它们的工作方式相似。
编辑:已更新,请参阅评论
这将读入一个文件,每次收到一大块数据时,它都会创建一个 api 调用并发送数据
<?php
require_once __DIR__ . '/vendor/autoload.php';
function async_send($config, $file, callable $proccessor)
{
$config['ssl'] = true === $config['ssl'] ? 's' : '';
$client = new \GuzzleHttp\Client([
'base_uri' => 'http' . $config['ssl'] . '://' . $config['domain'] . '/rest/all/V1/',
'verify' => false,
'http_errors' => false
]);
$loop = \React\EventLoop\Factory::create();
$filesystem = \React\Filesystem\Filesystem::create($loop);
$filesystem->getContents($file)->then(function($contents) use ($config, $proccessor, $client) {
$contents = $proccessor($contents);
$client->post($config['uri'], ['body' => $contents]);
});
}
$config = [
'domain' => 'example.com',
'ssl' => true
];
//somewhere later
$configp['uri'] = 'products';
async_send($configp, __DIR__ . 'my.csv', function ($contents) {
return json_encode($contents);
});
以防其他人正在尝试解决类似问题
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use React\HttpClient\Client as ReactClient;
function async_send($loop, $filePath, callable $proccessor)
{
echo "starting";
echo "\n\r";
try {
$filesystem = \React\Filesystem\Filesystem::create($loop);
$file = $filesystem->file($filePath);
$file->open('r')
->then(function ($stream) use ($loop, $proccessor){
$stream->on('data', function ($chunk) use ($loop, $proccessor) {
$proccessor($chunk);
});
});
} catch (\Exception $e) {
echo "failed";
echo "\n\r";
}
echo "ending reading";
echo "\n\r";
}
function callApiReal($loop, $fileChunk = null)
{
echo "ready to call api". PHP_EOL;
$uri = "https://testapi.com/";
try {
$client = new ReactClient($loop);
} catch (\Exception $e) {
echo "Error";
}
echo "ready to call api";
$request = $client->request('POST', $uri, $fileChunk);
$request->on('response', function ($response) use ($uri) {
$response->on('data', function ($data_chunk) {
echo 'data chunk from api received';
echo "\n\r";
});
// subscribe to listen to the end of the response
$response->on('end', function () use ($uri) {
echo "operation has completed";
echo "\n\r";
});
});
$request->on('error', function ($error) {
// something went bad in the request
echo "Damm!";
echo "\n\r";
});
$request->end();
}
// main loop
$loop = React\EventLoop\Factory::create();
//somewhere later
async_send($loop, __DIR__ . '/my.csv', function ($chunk) use ($loop) {
echo "calling api";
callApiReal($loop, $chunk);
echo "\n\r";
});
$loop->run();