Множественные запросы API с помощью ReactPHPPhp

Кемеровские программисты php общаются здесь
Ответить
Anonymous
 Множественные запросы API с помощью ReactPHP

Сообщение Anonymous »

Мои цели
Я совершенно новичок в 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);
});
}
Функция вызывается в функции getProductByMpn.

Возвращенное обещание из 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);
}
});
}
Самое смешное: когда я смешиваю их вместе, функция all() работает нормально и выводит результат.
Это смешанная функция. Я думаю, это как-то связано с функцией 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);
}
});
}
Результат all() соответствует ожиданиям. Он распечатывает результаты каждого запроса.
Есть ли другой способ разрешить промисы без использования wait() и как правильно разрешить промисы с помощью all()?

Подробнее здесь: https://stackoverflow.com/questions/792 ... h-reactphp
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Php»