Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”
This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.
Dart/Flutter
Following the elegant use of async await in JS in the previous chapter, we have deeply understood that there are complex asynchronous dependencies in actual business. Traditional THEN and await async have various defects, and cannot write codes well in the face of complex scenes. This article will take you through the complex asynchronous operations in DART, JS’s twin. Let’s get started
With confidence
According to our years of JS experience, the second second to write and JS similar is not easy? On the whole
Doesn’t it look very nice? Let’s add a return type to the two methods and try again, okay?
why?
How fat? Why, no!!
I have to say that DART sucks the type system
Let’s take a look at the following code and guess what the output will be.
Before we get to the answer, let’s change the code and add a double to list2.
I don’t know if you guessed, but we’ll find out
Why is this happening?? Do you feel overwhelmed??
And now for our tool man @Alex
Did you see the above dialogue a question mark? Why did I define List
to not work? If you do not directly declare a generic type after a derived conversion, the result will be the actual type of the derived type, and will be directly converted to the runtime type. I just ask, this pit is not pit, compilation can be compiled, the code directly OJBK, run when the error, this TM also no one… , suggest you carefully read the above dialogue, lest compile for a while, run direct crematorium…
Let’s look at the definition of the then method. It does have a generic, so that’s easy
Future<R> then<R>(FutureOr<R> onValue(T value), {Function? onError});
Copy the code
Improve the code
After the verification above, let’s modify the previous code
First, if we were to return a list of certain types, returning [err, null] in catchError would cause a type mismatch
Regardless of the exact type, we change the List to List
, and everything runs
Dart doesn’t support multiple types of TS, which is a good thing. In addition, it is not possible to directly deconstruct the list like js, and can only be used with.first. last.
Dart is a strongly typed language and does not support multiple list types like TS. Here we have explicit object associations for the returned results. We wrap an object to wrap the results. Totally fine, there is no JS mess and the correct type hints are included.
Now let’s design a class that contains a success result, an error message, a stack, and an exact value to indicate whether an error occurred. Based on the above, we can get a class that wraps our results. Doesn’t that look good?
class Any<T> {
final T? ok;
final dynamic err;
final dynamic stackTrace;
bool gethasErr => err ! =null;
Any.ok(this.ok, {this.err, this.stackTrace});
Any.err(this.err, this.stackTrace, {this.ok});
@override
String toString() {
return 'Any{ok: $ok, err: $err, stackTrace: $stackTrace} '; }}Copy the code
Complete code after modification
import 'dart:async';
Future<void> main() async {
var a = await any(err());
print(a);
print(a.runtimeType);
print(a.hasErr);
print(a.ok);
print(a.ok.runtimeType);
print(a.err);
print('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
var b = await any(succ());
print(b);
print(b.runtimeType);
print(b.hasErr);
print(b.ok);
print(b.ok.runtimeType);
print(b.err);
print('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =');
var c = await any(voidf());
print(c);
print(c.runtimeType);
print(c.hasErr);
// safe type check. void not any called.
// print(c.ok);
// print(c.ok.runtimeType);
print(c.err);
}
Future<String?> err() async {
throw Error();
}
Future<String> succ() async {
return "success";
}
Future<void> voidf() async {
print('void function.'); } Future<Any<T? >> any<T>(Future<T> future) {returnfuture.then<Any<T? >>((T t) {return Any.ok(t);
}).catchError((err, stackTrace) {
return Any.err(err, stackTrace, ok: null);
});
}
class Any<T> {
final T? ok;
final dynamic err;
final dynamic stackTrace;
bool gethasErr => err ! =null;
Any.ok(this.ok, {this.err, this.stackTrace});
Any.err(this.err, this.stackTrace, {this.ok});
@override
String toString() {
return 'Any{ok: $ok, err: $err, stackTrace: $stackTrace} '; }}Copy the code
So let’s run it
Isn’t it perfect?? When we encounter complex business scenarios like before, we can directly make simple judgments and say goodbye to n-layer nesting
var d1 = await any(doSomething1());
if (d1.hasErr) {
// do something..
return;
}
print(d1.ok);
// do something..
var d2 = await any(doSomething2());
if (d2.hasErr) {
// do something..
return;
}
print(d2.ok);
// do something..
var d3 = await any(doSomething3());
if (d3.hasErr) {
// do something..
return;
}
// more task...
Copy the code
To summarize
- Dart can also be used elegantly
async
、await
As long as the simple packaging, completely OJBK - Be aware of dart’s type system. Just because code compiles doesn’t mean it can run
- Some people might wonder why I like to use it
any
The word, rather thanto
After all,Promise.any
Future.any
That’s already been done. First of all, I don’t have a two-element array here, and then,any
This is also a good way to indicate that the return is either right or wrong, and that the right choice needs to be made
Handsome and beautiful people who want to run directly can run directly here
Finally, you can click here to join the QQ group FlutterCandies🍭 and communicate with various gurus
Dartpad source address (gist requires ladder)