php - 如何从 ReactPHP\Promise\Promise 中“提取”数据?
问题描述
免责声明:这是我第一次使用ReactPHP
“php promises”,所以解决方案可能只是盯着我的脸
我目前正在做一个需要创建 Slack 机器人的小项目。我决定使用Botman包并使用它的 Slack RTM 驱动程序。该驱动程序利用 ReactPHP 的 promise 与 RTM API 进行通信。
我的问题:
当我对命令进行机器人回复时,我想获取来自 RTM API 的检索响应,因此我可以缓存已发布消息的 ID。
问题是,响应是在其中一个中返回的,ReactPHP\Promise\Promise
但我根本不知道如何检索数据。
我在做什么:
因此,当触发命令时,机器人会发送回复 Slack:
$response = $bot->reply($response)->then(function (Payload $item) {
return $this->reply = $item;
});
但随后$response
包含一个 (empty?) ReactPHP\Promise\Promise
:
React\Promise\Promise^ {#887
-canceller: null
-result: null
-handlers: []
-progressHandlers: & []
-requiredCancelRequests: 0
-cancelRequests: 0
}
我也尝试过使用done()
instead of then()
,这就是(据我所知)官方 ReactPHP 文档建议您应该使用它来从 promise 中检索数据:
$response = $bot->reply($response)->done(function (Payload $item) {
return $this->reply = $item;
});
但随后$response
返回为null
.
有趣的是,在调试过程中,我尝试在var_dump($item)
里面做一个then()
但忘记删除 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();
}
你可以在这里看到它的完整来源看到它的完整来源。
请给我指出某种方向。我觉得我什么都试过了,但显然我错过了什么或做错了什么。
解决方案
ReactPHP 核心团队成员在这里。这里有一些选择和事情。
首先then
永远不会从 Promise 中返回值,它会返回一个新的 Promise,这样你就可以创建一个 Promise 链。因此,您在每个 then 中执行一个新的异步操作,该操作会接收前一个操作的结果。
其次done
,从不返回结果值,并且工作起来非常相似,then
但会从链中的前一个 Promise 中抛出任何未捕获的异常。
两者的问题then
是done
它们是您的解决方法。承诺 a 仅表示尚未完成的操作的结果。一旦操作准备好并解决承诺,它就会打电话给callable
你then
/ 。done
因此,最终您的所有操作都以callable
一种或另一种方式发生在最广泛的意义上。(这也可以是__invoke
类上的方法,具体取决于您如何设置它。还有为什么我对 PHP 中的短闭包如此兴奋7.4
。)
您在这里有两个选择:
callable
在's内运行所有操作- 使用RecoilPHP
前者意味着更多的思维导图和学习异步的工作原理以及如何围绕它来思考。后者使它更容易,但需要您在协程中运行每条路径(callable
使用一些很酷的魔法)。
推荐阅读
- python - 如果行仅包含停用词中的任何一个,则从文本文件中删除这些行
- angular - 如何根据 Firebase 中的值存储显示用户输出(Angular)
- python - 循环时间到前 15 分钟,除非在 10 分钟内
- dart - Flutter run --release crash: 在抛出 std::bad_alloc 的实例后调用终止
- python - 使用 Python 修改 JSON 文件
- javascript - Javascript/jQuery:从活动目录读取数据
- android - 当前使用哪种布局横向或纵向?
- python - Visual Studio Code (Mac OS) 重命名符号不起作用
- amazon-web-services - AWS lambda 提取大数据并上传到 s3
- javascript - -c 标志在 NodeJS 中的作用是什么?