Отказ от ответственности: я впервые работаю с ReactPHP
и "php promises", поэтому решение может просто смотреть мне в лицо ?
Я сейчас работаюна небольшом проекте, где мне нужно создать бот Slack.Я решил использовать пакет Botman и использовать его драйвер Slack RTM.Этот драйвер использует обещания ReactPHP для связи с RTM API.
Моя проблема:
Когда я отвечаю ботом на команду, я хочу получить get getответ от RTM API, так что я могу кэшировать идентификатор отправленного сообщения.
Проблема в том, что ответ возвращается внутри одного из этих ReactPHP\Promise\Promise
, но я просто не могу понять, как получитьданные.
Что я делаю:
Поэтому, когда команда запускается, бот отправляет ответ Slack:
$response = $bot->reply($response)->then(function (Payload $item) {
return $this->reply = $item;
});
Но тогда $response
состоит из (пусто?) ReactPHP\Promise\Promise
:
React\Promise\Promise^ {#887
-canceller: null
-result: null
-handlers: []
-progressHandlers: & []
-requiredCancelRequests: 0
-cancelRequests: 0
}
Я также пытался использовать done()
вместо then()
, что и есть (насколько я понимаю) официальные документы ReactPHP предлагают использовать для получения данных из обещания :
$response = $bot->reply($response)->done(function (Payload $item) {
return $this->reply = $item;
});
Но тогда $response
возвращается как null
.
ЗабавноДело в том, что во время отладки я пытался выполнить var_dump($item)
внутри then()
, но забыл удалить несуществующий метод в обещании.Но затем var_dump
фактически вернул данные ?
$response = $bot->reply($response)->then(function (Payload $item) {
var_dump($item);
return $this->reply = $item;
})->resolve();
Итак, из того, что я могу понять, я как-то должен снова «выполнить» обещание, даже если оно было решено до его возвращения.
Внутри метода ответа бота, это то, что происходит и как генерируется обещание ReactPHP:
public function apiCall($method, array $args = [], $multipart = false, $callDeferred = true)
{
// create the request url
$requestUrl = self::BASE_URL . $method;
// set the api token
$args['token'] = $this->token;
// send a post request with all arguments
$requestType = $multipart ? 'multipart' : 'form_params';
$requestData = $multipart ? $this->convertToMultipartArray($args) : $args;
$promise = $this->httpClient->postAsync($requestUrl, [
$requestType => $requestData,
]);
// Add requests to the event loop to be handled at a later date.
if ($callDeferred) {
$this->loop->futureTick(function () use ($promise) {
$promise->wait();
});
} else {
$promise->wait();
}
// When the response has arrived, parse it and resolve. Note that our
// promises aren't pretty; Guzzle promises are not compatible with React
// promises, so the only Guzzle promises ever used die in here and it is
// React from here on out.
$deferred = new Deferred();
$promise->then(function (ResponseInterface $response) use ($deferred) {
// get the response as a json object
$payload = Payload::fromJson((string) $response->getBody());
// check if there was an error
if (isset($payload['ok']) && $payload['ok'] === true) {
$deferred->resolve($payload);
} else {
// make a nice-looking error message and throw an exception
$niceMessage = ucfirst(str_replace('_', ' ', $payload['error']));
$deferred->reject(new ApiException($niceMessage));
}
});
return $deferred->promise();
}
Вы можете увидеть его полный источник здесь .
Пожалуйста, просто укажите мне в каком-то направлении.Я чувствую, что попробовал все, но, очевидно, я что-то упускаю или делаю что-то не так.