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
}
}
The warning from the async documentation page is relevant here:
There is currently basic support for async. For example, you can
currently write basic async functions that call other async functions.
However, we are currently finalizing other foundations (e.g. async
database, scheduling, and memory handling APIs) which will be required
to reach the full potential of async in production. We felt, though,
it would be useful to introduce the concept and technology of async
(even with basic functionality) in order to get developers used to the
syntax and some of the technical details.
So, the raw database queries you need to actually make use of async functions are unfortunately not available yet. The documentation linked above talks some about how async functions work in general, and includes an example of coalesced fetching, something that you can do with async functions right now.
The DB API is coming eventually, but isn't available yet, sorry!
HHVM 3.6 and newer
async functions info
The two HHVM PHP language keywords that enable async functions are async and await. async declares a function as asynchronous. await suspends the execution of an async function until the result of the asynchronous operation represented by await is available. The return value of a function that await can be used upon is an object that implements Awaitable<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 tips
The 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.
Related
The documentation stresses that I should use a new EntityManager for each request and there's even a middleware for automatically generating it or alternatively I can use em.fork(). So far so good.
The EntityRepository is a great way to make the code readable. I could not find anything in the documentation about how they relate to EntityManager instances. The express-ts-example-app example uses single instances of repositories and the RequestContext middleware. This suggests that there is some under-the-hood magic that finds the correct EntityManager instances at least with the RequestContext. Is it really so?
Also, if I fork the EM manually can it still find the right one? Consider the following example:
(async () => {
DI.orm = await MikroORM.init();
DI.em = DI.orm.em;
DI.companyRepository = DI.orm.em.getRepository(Company);
DI.invoiceRepository = DI.orm.em.getRepository(Invoice);
...
fetchInvoices(em.fork());
}
async function fetchInvoices(em) {
for (const company of await DI.companyRepository.findAll()) {
fetchInvoicesOfACompany(company, em.fork())
}
}
async function fetchInvoicesOfACompany(company, em) {
let done = false;
while (!done) {
const invoice = await getNextInvoice(company.taxnumber, company.lastInvoice);
if ( invoice ) {
DI.invoiceRepository.persist(invoice);
company.lastInvoice = invoice.id;
em.flush();
} else {
done = true;
}
}
}
Does the DI.invoiceRepository.persist() in fetchInvoicesOfACompany() use the right EM instance? If not, what should I do?
Also, if I'm not mistaken, the em.flush() in fetchInvoicesOfACompany() does not update company, since that belongs to another EM - how should I handle situations like this?
First of all, repository is just a thin layer on top of EM (an extension point if you want), that bares the entity name so you don't have to pass it to the first parameter of EM method (e.g. em.find(Ent, ...) vs repo.find(...).
Then the contexts - you need a dedicated context for each request, so it has its own identity map. If you use RequestContext helper, the context is created and saved via domain API. Thanks to this, all the methods that are executed inside the domain handler will use the right instance automatically - this happens in the em.getContext() method, that first checks the RequestContext helper.
https://mikro-orm.io/docs/identity-map/#requestcontext-helper-for-di-containers
Check the tests for better understanding of how it works:
https://github.com/mikro-orm/mikro-orm/blob/master/tests/RequestContext.test.ts
So if you use repositories, with RequestContext helper it will work just fine as the singleton repository instance will use the singleton EM instance that will then use the right request based instance via em.getContext() where approapriate.
But if you use manual forking instead, you are responsible use the right repository instance - each EM fork will have its own one. So in this case you can't use a singleton, you need to do forkedEm.getRepository(Ent).
Btw alternatively you can also use AsyncLocalStorage which is faster (and not deprecated), if you are on node 12+. The RequestContext helper implementation will use ALS in v5, as node 12+ will be requried.
https://mikro-orm.io/docs/async-local-storage
Another thing you could do is to use the RequestContext helper manually instead of via middlewares - something like the following:
(async () => {
DI.orm = await MikroORM.init();
DI.em = DI.orm.em;
DI.companyRepository = DI.orm.em.getRepository(Company);
DI.invoiceRepository = DI.orm.em.getRepository(Invoice);
...
await RequestContext.createAsync(DI.em, async () => {
await fetchInvoices();
})
});
async function fetchInvoices() {
for (const company of await DI.companyRepository.findAll()) {
await fetchInvoicesOfACompany(company)
}
}
async function fetchInvoicesOfACompany(company) {
let done = false;
while (!done) {
const invoice = await getNextInvoice(company.taxnumber, company.lastInvoice);
if (invoice) {
company.lastInvoice = invoice; // passing entity instance, no need to persist as `company` is managed entity and this change will be cascaded
await DI.em.flush();
} else {
done = true;
}
}
}
Is there any scenario where writing method like this:
public async Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return await DoAnotherThingAsync();
}
instead of this:
public Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return DoAnotherThingAsync();
}
would make sense?
Why use return await construct when you can directly return Task<T> from the inner DoAnotherThingAsync() invocation?
I see code with return await in so many places, I think I might have missed something. But as far as I understand, not using async/await keywords in this case and directly returning the Task would be functionally equivalent. Why add additional overhead of additional await layer?
There is one sneaky case when return in normal method and return await in async method behave differently: when combined with using (or, more generally, any return await in a try block).
Consider these two versions of a method:
Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return foo.DoAnotherThingAsync();
}
}
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
The first method will Dispose() the Foo object as soon as the DoAnotherThingAsync() method returns, which is likely long before it actually completes. This means the first version is probably buggy (because Foo is disposed too soon), while the second version will work fine.
If you don't need async (i.e., you can return the Task directly), then don't use async.
There are some situations where return await is useful, like if you have two asynchronous operations to do:
var intermediate = await FirstAsync();
return await SecondAwait(intermediate);
For more on async performance, see Stephen Toub's MSDN article and video on the topic.
Update: I've written a blog post that goes into much more detail.
The only reason you'd want to do it is if there is some other await in the earlier code, or if you're in some way manipulating the result before returning it. Another way in which that might be happening is through a try/catch that changes how exceptions are handled. If you aren't doing any of that then you're right, there's no reason to add the overhead of making the method async.
Another case you may need to await the result is this one:
async Task<IFoo> GetIFooAsync()
{
return await GetFooAsync();
}
async Task<Foo> GetFooAsync()
{
var foo = await CreateFooAsync();
await foo.InitializeAsync();
return foo;
}
In this case, GetIFooAsync() must await the result of GetFooAsync because the type of T is different between the two methods and Task<Foo> is not directly assignable to Task<IFoo>. But if you await the result, it just becomes Foo which is directly assignable to IFoo. Then the async method just repackages the result inside Task<IFoo> and away you go.
If you won't use return await you could ruin your stack trace while debugging or when it's printed in the logs on exceptions.
When you return the task, the method fulfilled its purpose and it's out of the call stack.
When you use return await you're leaving it in the call stack.
For example:
Call stack when using await:
A awaiting the task from B => B awaiting the task from C
Call stack when not using await:
A awaiting the task from C, which B has returned.
Making the otherwise simple "thunk" method async creates an async state machine in memory whereas the non-async one doesn't. While that can often point folks at using the non-async version because it's more efficient (which is true) it also means that in the event of a hang, you have no evidence that that method is involved in the "return/continuation stack" which sometimes makes it more difficult to understand the hang.
So yes, when perf isn't critical (and it usually isn't) I'll throw async on all these thunk methods so that I have the async state machine to help me diagnose hangs later, and also to help ensure that if those thunk methods ever evolve over time, they'll be sure to return faulted tasks instead of throw.
This also confuses me and I feel that the previous answers overlooked your actual question:
Why use return await construct when you can directly return Task from the inner DoAnotherThingAsync() invocation?
Well sometimes you actually want a Task<SomeType>, but most time you actually want an instance of SomeType, that is, the result from the task.
From your code:
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
A person unfamiliar with the syntax (me, for example) might think that this method should return a Task<SomeResult>, but since it is marked with async, it means that its actual return type is SomeResult.
If you just use return foo.DoAnotherThingAsync(), you'd be returning a Task, which wouldn't compile. The correct way is to return the result of the task, so the return await.
Another reason for why you may want to return await: The await syntax lets you avoid hitting a mismatch between Task<T> and ValueTask<T> types. For example, the code below works even though SubTask method returns Task<T> but its caller returns ValueTask<T>.
async Task<T> SubTask()
{
...
}
async ValueTask<T> DoSomething()
{
await UnimportantTask();
return await SubTask();
}
If you skip await on the DoSomething() line, you'll get a compiler error CS0029:
Cannot implicitly convert type 'System.Threading.Tasks.Task<BlaBla>' to 'System.Threading.Tasks.ValueTask<BlaBla>'.
You'll get CS0030 too, if you try to explicitly typecast it.
This is .NET Framework, by the way. I can totally foresee a comment saying "that's fixed in .NET hypothetical_version", I haven't tested it. :)
Another problem with non-await method is sometimes you cannot implicitly cast the return type, especially with Task<IEnumerable<T>>:
async Task<List<string>> GetListAsync(string foo) => new();
// This method works
async Task<IEnumerable<string>> GetMyList() => await GetListAsync("myFoo");
// This won't work
Task<IEnumerable<string>> GetMyListNoAsync() => GetListAsync("myFoo");
The error:
Cannot implicitly convert type 'System.Threading.Tasks.Task<System.Collections.Generic.List>' to 'System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable>'
I have a function loadData that loads some text from a file:
Future<String> loadAsset() async {
return await rootBundle.loadString('assets/data/entities.json');
}
The loadString method is from Flutter SDK, and is asynchronous.
The loadAsset method is then called in another method, that must me marked as async, since loadAsset is async and I need to use await:
Future<List<Entity>> loadEntities() async {
String jsonData = await loadAsset();
return parseData(jsonData);
}
The parseData method is not async, it receives a String, parse it, and return a list of objects:
List<Entity> parseData(String jsonString) {
...
}
But since loadEntities must be marked with async, this requires that it returns a Future, but in practice, it's not a Future because since I use await, it awaits for the loadAsset method to finish, then call the parseData funcion using the result.
This easily turns into a snowball of async call, because every method that uses loadEntities must be marked as async too.
Also, I can't use loadEntities in a class constructor, because the constructor should be marked as async, which is not allowed in Dart.
Am I using the async/await pattern in Dart wrong? How could I use the loadEntities method in a class constructor?
No, async is contagious and there is no way to go back from async to sync execution.
async/await is only syntactic sugar for methodThatReturnsFuture().then(...)
Marking a method with async is only to allow you to use await inside its body. Without async you would still need to return a Future for calling code to only execute after the result of loadAsset() becomes available.
You can use the Future returned from the async call directly. This would look something like this:
class HasAsync {
HasAsync() {
asyncFunction().then((val) {
print(val);
});
}
Future<int> asyncFunction() async {
int val = await otherFunction();
return val;
}
}
You just can't use await within the non-async function.
As you've tagged this with 'flutter', I'm going to guess this is within a flutter app. If that's the case look at the docs for FutureBuilder - it might help with what you're trying to do.
I know I may be too late for you to make any use of this answer but I am writing it anyways hoping someone will find it useful. So here is my two cents.
I had the same thought process as you did when I first tried to figure out what is asynchronous programming and how it can be used.
Since the question is regarding Flutter, I will use dart to explain this.
First, let's dive in to the the basic actually the purpose of using async await in asynchronous programming.
According to the flutter documentation, the purpose of async and await keywords is to declaratively mark a function as asynchronous and use it's results.
To define an async function, add async before the function body
The await keyword works only in async functions.
Therefore, whenever you try to get an output from a function marked as asynchronous it will have no option but to return a Future. Look at the following example for more clarification.
Firstly, you have a function which will do some calculations
Secondly, you have a simple function which gets data from an API by doing a simple http get request.
finally another function which will process some data and print some values.
void processInfo(){
calculateStuff();
Future<Map> decodedData = getDataFromInternet();
getDataProcessed(decodedData);
}
so in synchronous programming this would mean that all three functions will execute one after another. But let's say the second function getDataFromInternet() is called asynchronously. A simple implementation would be like below.
Future<Map> getDataFromInternet() async {
http.Response response = await http.get(this._apiPath);
Map decodedData;
if (response.statusCode != 200)
print("invalid response. cannot proceed!");
else {
decodedData = jsonDecode(response.body);
}
return decodedData;
}
So the above function is required to return a future. The question is why?
It's simple. In this case, it's because since we want to return something and by the time the return statement is executed and the data from the 'get request' may or may not be available at that moment.
Thus, the function returns a Future type result which and either be in complete state or incomplete state.
So how can we process this result? As a matter of fact this can be done in 3 ways.
1. Method One - Handle it as a promise
So once the getDataFromInternet() function returns a Future result in this example, you need the process that future result like how you'd handle a promise in javascript. Refer the code sample below.
void getDataProcessed(Future<Map> data) {
print('getting data from future map');
data.then((d) {
print(d);
});
}
2. Method Two - mark the parent function asynchronous (contagious way)
void processInfo() async{
calculateStuff();
//now you can simply await that result and process the result rather
//than handling a Future<Map> result in this case.
//Note: it is not required to use future variable because we are awaiting
//for result
Map decodedData = await getDataFromInternet();
getDataProcessed(decodedData);
}
so in this case the getDataProcessed() function will look something like this.
void getDataProcessed(Map data) {
//this will simply print the data object which is complete result which is by
//no way is a promise object
print(data);
}
3. Method Three - Use the results from the asynchronous method in a synchronous function (non-contagious way)
In this case the processInfo() function will change slightly, i.e. the getDataProcessed() will no longer be invoked in this method and will look something like this.
void processInfo(){
calculateStuff();
getDataFromInternet();
}
Instead of invoking getDataProcessed() in processInfo() function, we can use the result from getDataFromInternet() function to invoke the getDataProcessed() function.this mean we won't have to mark processInfo() as async and we can process getDataProcessed() method after we finish executing getDataFromInternet() method. The following code sample demonstrates how to do it.
void getDataFromInternet() async {
http.Response response = await http.get(this._apiPath);
Map decodedData;
if (response.statusCode != 200)
print("invalid response. cannot proceed!");
else {
decodedData = jsonDecode(response.body);
}
//in this case, since we are awaiting for get results response and the
//function is not expected to return anything the data type passed into
//getDataProcessed() function now will be of type Map rather than being type
//Future<Map> . Thus allowing it to be a synchronous function and without
//having to handle the future objects.
getDataProcessed(decodedData);
}
void getDataProcessed(Map data) {
//this will simply print the data object which is complete result which is by
//no way is a promise object
print(data);
}
So revising back this long answer,
async/await is just the declarative way to mark asynchronous functions
when an asynchronous function is called it can be handled in 3 ways.
get the return Future and handle it like a promise with the use of 'then()' function so no need to mark the parent
function async
mark the parent function async and handle the returned object with await to force the function to wait for the result.
call the desired function with the output of the async function at the end of the async function. This will allow the main
function to continue non-dependent functions while waiting for the
results of the async function and one the async function get the
results it can go in to the other function at the end and execute it
with the data received.
then and await are different. await will stop the program there until the Future task is finished. However then will not block the program. The block within then will be executed when the Future task is finished afterwards.
If you want your program to wait for the Future task, then use await. If you want your program to continue running and the Future task do it things "in the background", then use then.
As to your problem, I suggest redesign it. Do the loading assets and other async things that are needed for the constructor elsewhere. After these tasks are completed, then call the constructor.
I have the following WebAPI action and is wondering if returning Task<bool> and return _store.ContainerExistsAsync(container) directly is better;
I ask because, if I understand async/await correctly, the compiler creates a statemachine at the await to return to the same state. Returning the task directly without having to await it in the action, would that be theoretical faster?
public async Task<HttpResponseMessage> GetContainer(string container)
{
if (container.Length < 3 ||
container.Length > 63 ||
!Regex.IsMatch(container, #"^[a-z0-9]+(-[a-z0-9]+)*$"))
return Request.CreateResponse(HttpStatusCode.BadRequest, new { errors = new string[1] { "Container Name is not alowed." } })
return Request.CreateResponse<bool>(HttpStatusCode.OK, await _store.ContainerExistsAsync(container));
}
Yes, if you can implement an asynchronous method without async and await, then go ahead; async/await will add overhead.
This is commonly seen when the last line of a method has the only await and looks like return await ...;
In your particular example, I'm not 100% sure whether this would work since the method is doing something after the await.
It's easy enough to make it return the Task<bool> from ContainerExistsAsync directly, but the error handling would also need to change. If throwing a HttpResponseException works well enough, then yes, you would be able to implement an asynchronous method without using async.
is it possible to create your own futures in Dart to return from your methods, or must you always return a built in future return from one of the dart async libraries methods?
I want to define a function which always returns a Future<List<Base>> whether its actually doing an async call (file read/ajax/etc) or just getting a local variable, as below:
List<Base> aListOfItems = ...;
Future<List<Base>> GetItemList(){
return new Future(aListOfItems);
}
If you need to create a future, you can use a Completer. See Completer class in the docs. Here is an example:
Future<List<Base>> GetItemList(){
var completer = new Completer<List<Base>>();
// At some time you need to complete the future:
completer.complete(new List<Base>());
return completer.future;
}
But most of the time you don't need to create a future with a completer. Like in this case:
Future<List<Base>> GetItemList(){
var completer = new Completer();
aFuture.then((a) {
// At some time you need to complete the future:
completer.complete(a);
});
return completer.future;
}
The code can become very complicated using completers. You can simply use the following instead, because then() returns a Future, too:
Future<List<Base>> GetItemList(){
return aFuture.then((a) {
// Do something..
});
}
Or an example for file io:
Future<List<String>> readCommaSeperatedList(file){
return file.readAsString().then((text) => text.split(','));
}
See this blog post for more tips.
You can simply use the Future<T>value factory constructor:
return Future<String>.value('Back to the future!');
Returning a future from your own function
This answer is a summary of the many ways you can do it.
Starting point
Your method could be anything but for the sake of these examples, let's say your method is the following:
int cubed(int a) {
return a * a * a;
}
Currently you can use your method like so:
int myCubedInt = cubed(3); // 27
However, you want your method to return a Future like this:
Future<int> myFutureCubedInt = cubed(3);
Or to be able to use it more practically like this:
int myCubedInt = await cubed(3);
The following solutions all show ways to do that.
Solution 1: Future() constructor
The most basic solution is to use the generative constructor of Future.
Future<int> cubed(int a) {
return Future(() => a * a * a);
}
I changed the return type of the method to Future<int> and then passed in the work of the old function as an anonymous function to the Future constructor.
Solution 2: Future named constructor
Futures can complete with either a value or an error. Thus if you want to specify either of these options explicitly you can use the Future.value or Future.error named constructors.
Future<int> cubed(int a) {
if (a < 0) {
return Future.error(ArgumentError("'a' must be positive."));
}
return Future.value(a * a * a);
}
Not allowing a negative value for a is a contrived example to show the use of the Future.error constructor. If there is nothing that would produce an error then you can simply use the Future.value constructor like so:
Future<int> cubed(int a) {
return Future.value(a * a * a);
}
Solution 3: async method
An async method automatically returns a Future so you can just mark the method async and change the return type like so:
Future<int> cubed(int a) async {
return a * a * a;
}
Normally you use async in combination with await, but there is nothing that says you must do that. Dart automatically converts the return value to a Future.
In the case that you are using another API that returns a Future within the body of your function, you can use await like so:
Future<int> cubed(int a) async {
return await cubedOnRemoteServer(a);
}
Or this is the same thing using the Future.then syntax:
Future<int> cubed(int a) async {
return cubedOnRemoteServer(a).then((result) => result);
}
Solution 4: Completer
Using a Completer is the most low level solution. You only need to do this if you have some complex logic that the solutions above won't cover.
import 'dart:async';
Future<int> cubed(int a) async {
final completer = Completer();
if (a < 0) {
completer.completeError(ArgumentError("'a' must be positive."));
} else {
completer.complete(a * a * a);
}
return completer.future;
}
This example is similar to the named constructor solution above. It handles errors in addition completing the future in the normal way.
A note about blocking the UI
There is nothing about using a future that guarantees you won't block the UI (that is, the main isolate). Returning a future from your function simply tells Dart to schedule the task at the end of the event queue. If that task is intensive, it will still block the UI when the event loop schedules it to run.
If you have an intensive task that you want to run on another isolate, then you must spawn a new isolate to run it on. When the task completes on the other isolate, it will return a message as a future, which you can pass on as the result of your function.
Many of the standard Dart IO classes (like File or HttpClient) have methods that delegate the work to the system and thus don't do their intensive work on your UI thread. So the futures that these methods return are safe from blocking your UI.
See also
Asynchrony support documentation
Flutter Future vs Completer
#Fox32 has the correct answer addition to that we need to mention Type of the Completer otherwise we get exception
Exception received is type 'Future<dynamic>' is not a subtype of type 'FutureOr<List<Base>>
so initialisation of completer would become
var completer= new Completer<List<Base>>();
Not exactly the answer for the given question, but sometimes we might want to await a closure:
flagImage ??= await () async {
...
final image = (await codec.getNextFrame()).image;
return image;
}();
I think it does create a future implicitly, even though we don't pass it anywhere.
Here a simple conditional Future example.
String? _data;
Future<String> load() async {
// use preloaded data
if (_data != null) return Future<String>.value(_data);
// load data only once
String data = await rootBundle.loadString('path_to_file');
_data = data;
return data;
}