Приветствую!
Я совершенно новичок в ReactPHP, асинхронном программировании и разработке программного обеспечения. В настоящее время я работаю над API, который хочу сделать асинхронным. API должен выполнять огромное количество запросов API к внешним API.
Моя идея состоит в том, чтобы запускать запросы API в фоновом режиме, чтобы он не блокировал дальнейшие запросы клиентов, но я не мог заставить его работать должным образом.
Во всем API нам приходится отправлять запросы к отдельным дистрибьюторам, у которых есть разные способы обработки запросов API, поэтому нам приходится реализовывать каждый дистрибьютор индивидуально.
В API я использую ReactPHP EventLoop.
С чем я работаю
Я работаю с React\Promise\all(). Поэтому я создаю 5 тестовых обещаний и передаю их всем():
Информация: я использую Guzzle для выполнения запросов, потому что мне нужно поместить заголовки в параметр Curl для этого конкретного дистрибьютора. .
Код: Выделить всё
private function requestProduct($id, $access_token, $request_url, $client_id)
{
$request_url = str_replace(' ','',$request_url);
$data = [
'currency' => 'EUR',
'limit' => 1,
'search' => $id
];
$request_url .= "search?" . http_build_query($data);
$this->setRequestUrl($request_url);
$header = [
"content-type: application/x-www-form-urlencode",
"accept: application/json",
"authorization: Bearer $access_token",
"client_id: $client_id"
];
// $this->setHeader($header);
$this->client = new Client();
for ($i = 0; $i < 5; $i++) {
$promises[] = new Promise(function ($resolve, $reject) use ($request_url, $header, $i) {
try {
echo "Starting async request {$i} to URL: {$request_url}" . PHP_EOL;
$this->client->getAsync($request_url, [
'curl' => [
CURLOPT_HTTPHEADER => $header,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]
])
->then(
function (ResponseInterface $response) use ($resolve, $i) {
$content = $response->getBody()->getContents();
$decodedResponse = json_decode($content, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('Invalid JSON response');
}
echo "Request {$i} completed successfully." . PHP_EOL;
$resolve($decodedResponse);
},
function (Exception $e) use ($reject, $i) {
echo "Error during async GET request {$i}: {$e->getMessage()}" . PHP_EOL;
$reject($e);
}
);
} catch (Exception $e) {
echo "Unexpected error in request {$i}: {$e->getMessage()}" . PHP_EOL;
$reject($e);
}
});
}
echo "Waiting for all promises to resolve" . PHP_EOL;
// Wait for all promises to resolve
return all($promises)
->then(function($responses) {
$result = [];
echo "All Promises resolved" . PHP_EOL;
echo gettype($responses) . PHP_EOL;
foreach ($responses as $i => $response) {
// print_r($response);
$result[$i] = $response['status'];
echo "Result {$i} decoded" . PHP_EOL;
}
print_r($result);
return $result;
})
->catch(function($error) {
echo "An error occurred: {$error->getMessage()}" . PHP_EOL;
throw new Exception("Error in all()", 500);
});
}
Возвращенное обещание из all() должно быть разрешено в контроллере.
Код: Выделить всё
public function getProductByMpn($request)
{
try {
$body = $request->getParsedBody();
$distributor = DistributorHelper::getDistributorNameFromPath($request);
$distributorID = $body['linr'];
$mpn = $body['mpn'] ?? null;
if (!$distributor || !$mpn || !$distributorID) {
throw new Exception('Missing distributor, distributor ID or mpn', 400);
}
return $this->distributorService
->getProductByMpn($distributor, $mpn, $distributorID)
->then(function ($response) {
echo "Response successful". PHP_EOL;
return JsonResponse::ok($response);
})
->catch(function ($error) {
echo "Error in getProductByMpn: {$error->getMessage()}" . PHP_EOL;
throw new Exception("Error in getProductByMpn: {$error->getMessage()}", 500);
});
} catch (Exception $e) {
return JsonResponse::individual($e->getCode(), ['error' => $e->getMessage()]);
}
}
Проблема в том, что она не решается. Вместо этого кажется, что он где-то застревает. Я думаю, что сделал что-то не так при разрешении своих обещаний, но не могу найти ошибку.
Я также попробовал один запрос API, и он работает совершенно нормально:
Код: Выделить всё
private function requestProduct($id, $access_token, $request_url, $client_id)
{
$request_url = str_replace(' ','',$request_url);
$data = [
'currency' => 'EUR',
'limit' => 1,
'search' => $id
];
$request_url .= "search?" . http_build_query($data);
$this->setRequestUrl($request_url);
$header = [
"content-type: application/x-www-form-urlencode",
"accept: application/json",
"authorization: Bearer $access_token",
"client_id: $client_id"
];
// $this->setHeader($header);
$this->client = new Client();
return new Promise(function ($resolve, $reject) use ($request_url, $header) {
try {
echo "Starting async request to URL: {$request_url}" . PHP_EOL;
$this->client->getAsync($request_url, [
'curl' => [
CURLOPT_HTTPHEADER => $header,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]
])
->then(
function (ResponseInterface $response) use ($resolve) {
$content = $response->getBody()->getContents();
// echo "Response received: $content" . PHP_EOL;
$decodedResponse = json_decode($content, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('Invalid JSON response');
}
$resolve($decodedResponse);
},
function (Exception $e) use ($reject) {
echo "Error during async GET request: {$e->getMessage()}" . PHP_EOL;
$reject($e);
}
)
->wait(); // has to stand here to resolve correctly?
} catch (Exception $e) {
echo "Unexpected error: {$e->getMessage()}" . PHP_EOL;
$reject($e);
}
});
}
Это смешанная функция. Я думаю, это как-то связано с функцией wait() в одном промисе. Если в обещании нет функции wait(), оно тоже не работает.
Код: Выделить всё
private function requestProduct($id, $access_token, $request_url, $client_id)
{
$request_url = str_replace(' ','',$request_url);
$data = [
'currency' => 'EUR',
'limit' => 1,
'search' => $id
];
$request_url .= "search?" . http_build_query($data);
$this->setRequestUrl($request_url);
$header = [
"content-type: application/x-www-form-urlencode",
"accept: application/json",
"authorization: Bearer $access_token",
"client_id: $client_id"
];
// $this->setHeader($header);
$this->client = new Client();
for ($i = 0; $i < 5; $i++) {
$promises[] = new Promise(function ($resolve, $reject) use ($request_url, $header, $i) {
try {
echo "Starting async request {$i} to URL: {$request_url}" . PHP_EOL;
$this->client->getAsync($request_url, [
'curl' => [
CURLOPT_HTTPHEADER => $header,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]
])
->then(
function (ResponseInterface $response) use ($resolve, $i) {
$content = $response->getBody()->getContents();
$decodedResponse = json_decode($content, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('Invalid JSON response');
}
echo "Request {$i} completed successfully." . PHP_EOL;
$resolve($decodedResponse);
},
function (Exception $e) use ($reject, $i) {
echo "Error during async GET request {$i}: {$e->getMessage()}" . PHP_EOL;
$reject($e);
}
);
} catch (Exception $e) {
echo "Unexpected error in request {$i}: {$e->getMessage()}" . PHP_EOL;
$reject($e);
}
});
}
echo "Waiting for all promises to resolve" . PHP_EOL;
// Wait for all promises to resolve
all($promises)
->then(function($responses) {
$result = [];
echo "All Promises resolved" . PHP_EOL;
echo gettype($responses) . PHP_EOL;
foreach ($responses as $i => $response) {
// print_r($response);
$result[$i] = $response['status'];
echo "Result {$i} decoded" . PHP_EOL;
}
print_r($result);
return $result;
})
->catch(function($error) {
echo "An error occurred: {$error->getMessage()}" . PHP_EOL;
throw new Exception("Error in all()", 500);
});
return new Promise(function ($resolve, $reject) use ($request_url, $header) {
try {
echo "Starting async request to URL: {$request_url}" . PHP_EOL;
$this->client->getAsync($request_url, [
'curl' => [
CURLOPT_HTTPHEADER => $header,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]
])
->then(
function (ResponseInterface $response) use ($resolve) {
$content = $response->getBody()->getContents();
// echo "Response received: $content" . PHP_EOL;
$decodedResponse = json_decode($content, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('Invalid JSON response');
}
$resolve($decodedResponse);
},
function (Exception $e) use ($reject) {
echo "Error during async GET request: {$e->getMessage()}" . PHP_EOL;
$reject($e);
}
)
->wait(); // has to stand here to resolve correctly?
} catch (Exception $e) {
echo "Unexpected error: {$e->getMessage()}" . PHP_EOL;
$reject($e);
}
});
}
Есть ли другой способ разрешить промисы без использования wait() и как правильно разрешить промисы с помощью all()?
Надеюсь, кто-нибудь сможет мне помочь в этом случае. Я не нашел другого случая, похожего на этот.
Заранее спасибо.
ps: я никогда раньше не задавал здесь вопросов , поэтому понятия не имею, как это правильно сделать.
Подробнее здесь: https://stackoverflow.com/questions/792 ... h-reactphp
Мобильная версия