preface

Many people feel that the Future in flutter is the same as the Promise in JavaScript, but the system description only uses a simple async and await. In fact, they have the same principle and similar use methods

Async/await is really just a use of Future or Proimise, but it’s not obvious

Future

Future and async and await

If we define a method and compare the definition of an asynchronous function, we’ll see that the two are the same thing

// Define two methods, one with a return value and one without
Future<int> getUserInfo() async {
  print(789);
  return 1;
}

//Future getUserInfo2() async is the same as below
getUserInfo2() async {
  print(123);
  return 2;
}

// Test method
testGetUserInfo() {
  final user1 = getUserInfo();
  print(user1);
  final user2 = getUserInfo2();
  print(user2);
}

testGetUserInfo2() async {
  final user1 = await getUserInfo();
  print(user1);
  final user2 = await getUserInfo2();
  print(user2);
}
Copy the code

After executing the two test codes separately, the following results are returned

/ / testGetUserInfo execution
789
Instance of 'Future<int>'
123
Instance of 'Future<dynamic>'

/ / testGetUserInfo2 execution
789
1
123
2
Copy the code

The test results further show that the two functions return a Future object by default, where the function that does not return a value returns a Future object whose generic type is arbitrary Dynamic

If an await is used, the function will block execution until the execution inside the await completes and the result is returned

As mentioned earlier, the “await” function is blocked and put in a queue to delay execution. After all, the flutter mode is single-threaded and the Future is just emulating multi-threaded operations

The use of asynchronous functions

Having seen the relationship between Future and async above, let’s take a closer look at writing an asynchronous function

Async is an encapsulated Future function that returns a Future as a synchronous function, so you need to await it to get an asynchronous effect

//Future is similar to js Promise
Future delay1Second() async {
  print("I want to sleep.");
  sleep(Duration(seconds: 1));
  print("Sleep over.");
}
// This code is exactly the same as above, except that the system automatically wraps a Future
Future delay1SecondReplace() {
  return Future(() {
    print("I'm gonna sleep on it.");
    sleep(Duration(seconds: 1));
    print("Ready to sleep.");
  });
}
Copy the code

The above test results are not listed, as expected

Future advanced use

Promise was mentioned earlier, and Future can be used in the same way

If you need to process the result of some asynchronous function, you will not be able to use async and await

Here is a method that calls back a result asynchronously, in the form of a closure

// I called a third party, in the form of a closure, to call a result asynchronously
threeMethod(Function(int? result) completed) {
  Future.delayed(Duration(seconds: 2), () {
    print("I'm a three-way time consuming algorithm, and it takes about 2s to get something.");
    // Take a random int with a maximum value of 10
    if (Random().nextInt(10) % 10 > 4) {
      completed(5);
    }else {
      completed(null); }}); }Copy the code

For those of you who have written javascript, this is something I can do with a Promise + resolve, Reject, such as the following

/ / Promise version
workThreeMethod() {
  return Promise((resolve, reject) = > {
    threeMethod((res) {
      // Return null as an error
      if (res == null) {
        // You can also return completed without error, so there is no catch outside
        reject(new Error("Calculation error, return an error, need outside catch"));
      }else {
        resolve(5); }})}); }Copy the code

But what if there is no Resolve, Reject in Future?

The system provides the Completer class, as shown below, and will find that, apart from eliciting one more object, it is too similar

workThreeMethod() {
  // If you don't want to pass out the value, the generic type is void, otherwise use the specified type, or leave it blank (the default is dynamic)
  final completer = Completer<int>();
  threeMethod((res) {
    // Return null as an error
    if (res == null) {
      // You can also return completed without error, so there is no catch outside
      //await an error, crash,.catch
      completer.completeError("Calculation error, return an error, need outside catch");
    }else {
      // return to result, await is result of callback here
      completer.complete(5); }});return completer.future;// Finally return a future
}
Copy the code

The following is the correct call scenario, for errors

// This is a callback error
testWorkThreeMethod() {
  workThreeMethod().then((res) {
    print('res:${res}');
  }).catchError((err) {
    print('err:' + err);
  });
}

// We can also write it this way, so that the original error of the function will also be here
testWorkThreeMethod2() async {
  try {
    final res = await workThreeMethod();
    print(res);
  }catch(err) { print(err); }}Copy the code

As shown below, you can see that the two executions have the same result

I'm a three-way time consuming algorithm, and it takes about 2s to get a responseerr: calculation error, return an error, need outsidecatchHere I am a three-way time consuming algorithm, about 2s before the corresponding calculation error, return an error, need to outsidecatchtheCopy the code

Ps: The second one catches not only its own completeError, but also its own code’s error

The last

The principle of Future is the same as Promise, and if other languages have similar principles, you can try to see if similar things can be strung together

Also, the “All” and “Future” in Promise

For example, any in Future, which takes the Future array, returns a Future, and the result is an array type

After watching, is not the feeling very simple, come and try it