How modify the following code to get article data and top articles asynchronously in hack ?
class ArticleController
{
public function viewAction()
{
// how get
$article = $this->getArticleData();
$topArticles = $this->getTopArticles();
}
private function getArticleData() : array
{
// return article data from db
}
private function getTopArticles() : array
{
// return top articles from db
}
}
async
functions infoThe two HHVM PHP language keywords that enable async functions are
async
andawait
.async
declares a function as asynchronous.await
suspends the execution of anasync
function until the result of the asynchronous operation represented byawait
is available. The return value of a function thatawait
can be used upon is an object that implementsAwaitable<T>
.
You have an example in the documentation (1). There is a discussion about asynchronous functions in the language specification as well (2).
It actually took me some time to realize how to use and call the asynchronous functions, so I think you will find some more info useful.
We have these two functions: foo()
and bar()
.
async function foo(): Awaitable<void> {
print "executed from foo";
}
async function bar(int $n): Awaitable<int> {
print "executed from bar";
return $n+1;
}
Let's experiment some ways to call these two functions:
foo(); // will print "executed from foo"
bar(15); // will print "executed from bar"
$no1 = bar(15); // will print "executed from bar"
print $no1; // will output error, because $number is not currently an `int`; it is a `WaitHandle`
$no2 = bar(15)->join(); // will print "executed from bar"
print $no2; // will print 16
AsyncMysqlClient
tipsThe connection to a MySQL database is made with AsyncMysqlClient::connect
asynchronous function which returns an ExternalThreadEventWaitHandle
to an AsyncMysqlConnection
.
You can perform query
or queryf
on an AsyncMysqlConnection
. Note: the data you send to a queryf
is properly escaped by the function.
A query you perform on an AsyncMysqlConnection
returns either an AsyncMysqlQueryResult
(when the query performs ok) or AsyncMysqlQueryErrorResult
(if the query goes wrong; then you can treat errors with the mysql_error()
, mysql_errno()
and failureType()
members of this class). Both AsyncMysqlQueryResult
and AsyncMysqlQueryErrorResult
extend AsyncMysqlResult
abstract class.
Below is a probable implementation of your class:
class ArticleController {
private AsyncMysqlConnection $connection;
public async function viewAction(int $articleId): Awaitable<void> {
$this->connection = await AsyncMysqlClient::connect( /* connection data */ );
$article = await $this->getArticleData($articleId);
}
public async function getArticleData(int $id): Awaitable<?Vector> {
$articleDataQuery = await $this->connection->queryf("SELECT * FROM articles WHERE id %=d", $id);
if($articleDataQuery instanceof AsyncMysqlQueryErrorResult) {
throw new Exception("Error on getting data: ".$articleDataQuery->mysql_error());
}
// Considering that $id represents a unique id in your database, then
// you are going to get only one row from your database query
// so you return the first (and only) row in the query result
if($articleDataQuery->numRows() == 1) {
return $articleDataQuery->mapRowsTyped()[0];
}
return null;
}
}
P.S. I hope it is not too late for this answer and I hope it helps you. If you consider this useful, please, accept it.