【发布时间】:2019-06-13 06:19:57
【问题描述】:
免责声明:这是我第一次使用 ReactPHP 和“php promises”,所以解决方案可能只是盯着我的脸 ????
我目前正在做一个需要创建 Slack 机器人的小项目。我决定使用Botman 包并使用它的 Slack RTM 驱动程序。该驱动程序利用 ReactPHP 的 Promise 与 RTM API 进行通信。
我的问题:
当我让机器人回复命令时,我想从 RTM API 中获取 get 检索响应,这样我就可以缓存已发布消息的 ID。
问题是,响应是在其中一个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(),这就是(据我所知)official ReactPHP docs suggest you should use to retrieve data from a promise:
$response = $bot->reply($response)->done(function (Payload $item) {
return $this->reply = $item;
});
但随后$response 返回为null。
有趣的是,在调试过程中,我尝试在 then() 中执行 var_dump($item),但忘记删除 promise 上不存在的方法。但随后var_dump 居然返回了数据????
$response = $bot->reply($response)->then(function (Payload $item) {
var_dump($item);
return $this->reply = $item;
})->resolve();
所以据我所知,就好像我需要再次“执行”承诺,即使它在返回之前已经解决。
在 Bot 的回复方法中,这是发生了什么以及如何生成 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();
}
你可以看到它的完整来源here。
请给我指明一个方向。我觉得我什么都试过了,但显然我错过了什么或做错了什么。
【问题讨论】:
标签: php promise slack-api reactphp