Three friends of AsynchronyFuture.async,await

1.1 Remember them

  • Dart is single-threadedModel language, there is no main thread/child thread. One thread completes all asynchrony.
  • Even though it is a single thread, it also needs to do the asynchronous operation thing, which is coveredEvent QueueEvent LoopBut in fact, it is impossible to leaveFutureClasses andasync,awaitDry asynchrony can’t get rid of these three

From the picture, we can see. There are two things

  • Micortask QueueMicrotask queue
  • Event QueueThe event queue
  • Queue Queue, fifO fifO fifO

The Micortask Queue has a high priority and can not process the Event Queue until it is finished

The Micortask Queue is usually not involved, and all of our network operations, IO and so on are done asynchronously in the Event Queue.

(We all know asynchrony, concentrating on shitting is synchrony, while playing with your phone is asynchrony.)

I found two pictures on the Internet. Labeled as

See figure 1

See figure 2

aboutFutureClasses andasync,awaitSome official explanations, like jump to see

1.2. The anchor shouts, “Three, two, one, example.

Example 1 is the simplest demonstration

code

import 'dart:core';
void main() {
  Future((){
    print('Future1 here is going to be executed in EventQueu ');
  });
  // Execute after 3 seconds
  Future.delayed(Duration(seconds: 3), () {
    print('Future2 here is going to be executed in EventQueu ');
  });
}
Copy the code

.

The output

So Future1 is going to be executed in EventQueu and Future2 is going to be executed in EventQueuCopy the code

Example 1: The simplest asynchrony

  • What is written later is executed first
import 'dart:core';

void main() {
  // It will be implemented after the meeting
  Future((){
    print('I am a Future');
  });
  
  // This will be executed
  print('I'm writing code in the Future, but I'm going to show the execution, because the Future is an asynchronous operation that goes into the event queue.');
}
Copy the code

Output..

I'm the code in the Future, but I'm going to show the execution, because a Future is an asynchronous operation that's going into an event queue. I'm a FutureCopy the code

Seeing this, it is necessary to say:

In normal cases, main > MicroTask Queue > Event Queue

Remember him remember him remember him !!!!!!!!!!!!!!!!!!!!!!!!!!!

So ah. Needless to say, Future is asynchronous

So is it ok or is it not ok to do the above code sequentially? The Future executes first? Of course it is ok, need to use await

I. 3. The three states of Future

import 'dart:core';
void main() {
  Future(() {
    print('Unfinished state');
  })
      .then((value) => print('Completed state'))
      .catchError((value) => print('Abnormal state'));
}
Copy the code

Or write (less readable)

import 'dart:core';

void main() {
  Future(() {
    print('Unfinished state');
  }).then((value) => print('Completed state')).catchError((value) => print('Abnormal state'));
}
Copy the code

Output..

Incomplete Status Completed statusCopy the code

Second,awaitasyncCome on stage

awaitasyncIt’s usually used together,

The simplest asynchronous example is main > MicroTask Queue > Event Queue, where the main code specifies the Future in the Event queue before it is executed.

So, how do we get the code in order, that is, after the Future is executed, to execute the code below it?

The answer is to use await.

2.1 The function and premise of await

Await the role of

  • Indicates that the asynchronous task will be executed after it is completed.
  • Await only occurs inside asynchronous functions and allows us to perform asynchronous tasks as if we were writing synchronous code without using callbacks.
  • Await can only appear in async functions

Await the premise

Two conditions must be met to use the await keywordCopy the code
  • The current function must be asynchronous (that is, a function that contains the keyword async in its header)
  • Tasks decorated with await must be asynchronous tasks

Ii.2 Functions of Async

  • Async is used to indicate that a function is asynchronous. The defined function returns a Future object. Callbacks can be added using then.
  • Async function that returns a Future object. If no Future object is returned, the returned value is automatically wrapped as a Future object.
  • Using the Future with async and await makes the code look like synchronous code, but it is actually executed asynchronously

.

The code:

Future, await and async are used together

import 'dart:core';

// If async is used, the return value must be a Future object, so the return value of main is Future
      
Future<void> main() async {
  print('First line of code');
  /* -- await the async task before continuing. Await only occurs inside asynchronous functions and allows us to perform asynchronous tasks as if we were writing synchronous code without using callbacks. To use the await keyword, two conditions must be met: the current function must be an asynchronous function (i.e. a function that contains the keyword async in the function header); Tasks decorated with await must be asynchronous tasks */
  var fut = await Future((){
    print('I am a Future');
  });
  // This will be executed
  print('I am writing code after Future, because I used await before, SO I am executing after');
}
Copy the code

.

Output:

The first line of code I am a Future. I am the code written after the Future. Because I am using await in front, I am executing afterCopy the code

At this point, the three brothers Future, await and async all appear, and the combination of the three is the most used scene. It's not like they're three brothers, but let's say it.

See the foundation, basic use is enough.

You can read on if you’re interested.

Third, Future common methodsvalue delayed

3, 1Future.value()

  • Creates a Future that returns the specified value

Create a Future object from value. Vuale can be either a definite value or a Future object. This method uses the internal immediate function, which uses scheduleMicrotask to update the Future values in the MicroTask queue.

The value of the sample

import 'dart:core';

void main() {
  var future=Future.value(1);
  print(future);
  // Instance of 'Future
      
       '
      

  var futS=Future.value('Joe');
  print(futS);
  // output: Instance of 'Future
      
       '
      
}
Copy the code

3. 2, the Future of ()

  • Create a future that is deferred.
import 'dart:core';

void main() {
  var futureDelayed = Future.delayed(Duration(seconds: 2), () {
    print("Future.delayed");
    return 2;
  });
}
Copy the code

Well, there’s nothing to say about that, okay

4. Handle Future results. Then, catchError, whenComplete, timeout

The following four methods are commonly used to process the result of a Future, of which THEN is the most common

  • Then: The creation is completeFutureObject can be passedthenMethod receivesFutureResults.
  • CatchError: whenFutureNo correct access to results occurs when an exception occurs except inthenRegister in methodonErrorCallbacks can also be passedcatchErrorMethod listens for exceptions.
  • WhenComplete: when theFutureWhen in the finished state, callbacks registered with this method are invoked, regardless of whether the result is success or failurefinallyCode block.
  • Timeout: indicates the timeout processing

1. Then method

Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});

  • Used to add a callback when the Future is complete.
  • thenmethodsonValueThe return value of the callback function isFutureOr<R>, indicating that the callback function can return oneFutureObject, or return oneTThe value of the type
  • thenMethod takes two callback function parameters,onValueReceived a successful callback, optionalonErrorReceive failed callback.

Then example 1

import 'dart:core';

void main() {
  var future = Future(() {
    //do compution
    return "future value";
  });
  future.then((value) {
    print("Successful onValue:$value");
  }, onError: (error) {
    print("Failure onError$error");
  });
}
Copy the code

.. output:

Success onValue: Future ValueCopy the code

Then example 2

Chain calls

import 'dart:core';

void main() {
  Future.value(1).then((value) {
    return Future.value(value + 2);
  }).then((value) {
    return Future.value(value + 3);
  }).then(print);
  // Prints 6
}
Copy the code

Then example 3

With THEN, multiple asynchronous network requests can be made, executed sequentially from top to bottom, rather than horizontally nested through callback.

var future = Future(() {
   //do compution
    return "future value";
  });

future.then((value) {
    print("onValue: $value");
    var otherFuture = Future(() {
        //do request
        return "request value";
    });
    return otherFuture;
}, onError: (error) {
    print("onError $error");
}).then((value) {
    print("onValue: $value");
});


Copy the code

4.2, catchError method

Future<T> catchError(Function onError, {bool test(Object error)});

In addition to registering the onError callback in the THEN method, you can also listen for the exception through the catchError method when the Future does not get the result correctly.

Example 1 catchError

import 'dart:core';

void main() {
  var future = Future(() {
    //do compution
    throw Exception("exception occured");
  });
  future.then((value){
    print("onValue: $value");
  }).catchError((error) {
    print("catchError $error"); });CatchError Exception: Exception occured
}
Copy the code

The catchError method also has an optional test function argument. When an exception occurs, the test function will be called first. If this function returns false, the exception will not be processed by the catchError function and will continue to be passed. If the test function returns true, the catchError function handles the exception. If no test function is provided, the default is true.

Example 2 onError in catchError and then

What is the difference between the onError argument of the then method and the catchError method?

The catchError method is used to catch the onValue function of the former THEN method, but the onValue function of the former THEN method cannot catch the exception of the onValue function of the former THEN method.

void main() {
  var future = Future(() {
    return "future value";
  });
  future.then((value){
    print("onValue: $value");
    throw Exception("exception occured");
  }, onError: (error) {
    print("onError $error");
  }).catchError((error) {
    print("catchError $error");
  });

}
Copy the code

Output..

onValue: future value\
catchError Exception: exception occured\

Copy the code

The exception is caught by catchError, but onError is not called.

4. 3, whenComplete

  • The Future object also has a whenComplete method, through which callbacks registered will be invoked when the Future is in the completed state, whether the result is success or failure, similar to the finally code block.

  • The whenComplete method has an argument type of FutureOr and returns a Future

    . Indicates that the method can return a value or a Future object.

  • After the whenComplete function, you can call the then, catchError, and other methods, but the later registration callback does not get the value returned by whenComplete, but the value before whenComplete. This logic is equivalent to the following code

In the code

Future<T> whenComplete(action()) {
  return this.then((v) {
    var f2 = action();
    if (f2 is Future) return f2.then((_) => v);
    return v
  }, onError: (e) {
    var f2 = action();
    if (f2 is Future) return f2.then((_) { throw e; });
    throw e;
  })
Copy the code

4. Timeout method

Future<T> timeout(Duration timeLimit, {FutureOr<T> onTimeout()})

  • timeoutMethod creates a new Future object and receives oneDurationThe type oftimeLimitParameter to set the timeout period.
  • If the originalFutureFinish before the timeout, the end result is the originalFutureThe value of the;
  • Is generated if the timeout period has not been completedTimeoutExceptionThe exception.
  • The method has oneonTimeoutOptional. If set, this function is called when a timeout occurs and returns a new value for the Future instead of being generatedTimeoutException.

Future some relatively seldom used methods

V. 1. Foreach method

Future.foreach(Iterable elements, FutureOr action(T element))

Based on a collection, a series of futures are created and executed in sequence. For example, in the following example, {1,2,3} creates three futures with a delay corresponding to the number of seconds. The result is that 1 is printed after 1 second, 2 seconds after 2 seconds, and 3 seconds after 3 seconds. The total time is 6 seconds.

Future.foreach ({1,2,3}, (num){return future.delayed (Duration(seconds: num),(){print(num); }); });Copy the code

A. wait B. wait C. wait D. wait

Future.wait ( Iterable<Future> futures,{bool eagerError: false, void cleanUp(T successValue)})

Used to wait for multiple futures to complete and collect their results. There are two possible outcomes:

  • If all futures return normal results: the return result of the future is the set of results for all specified futures
  • If one future returns an error: the future returns the value of the first error.

For example, in the following example, a Future is also created with three delays for each second. The result is that [1, 2, 3] is output after the total time has passed by 3 seconds. Contrast this with the example above, which executes multiple Futures sequentially and asynchronously.

var future1 = new Future.delayed(new Duration(seconds: 1), () => 1); var future2 = new Future.delayed(new Duration(seconds: 2), () => 2); var future3 = new Future.delayed(new Duration(seconds: 3), () => 3); Future.wait({future1,future2,future3}).then(print).catchError(print); [1, 2, 3]Copy the code

If future2 and future3 are raised with an error, future.wait will result in the error value of this future2.

var future1 = new Future.delayed(new Duration(seconds: 1), () => 1); Var future2 =new future.delayed (new Duration(seconds: 2), () => throw "throw error2"); Var future3 = new future.delayed (new Duration(seconds: 3), () => throw "throw error3"); Future.wait({future1,future2,future3}).then(print).catchError(print); // Throw error2Copy the code

三.3, Do you like it?

Returns the result of the first future executed, regardless of whether the result is correct or error.

For example, in the following example, three different futures were created using future.delayed (), and the first completion returns the result of the Future that was delayed by 1 second.

 Future
      .any([1, 2, 5].map(
          (delay) => new Future.delayed(new Duration(seconds: delay), () => delay)))
      .then(print)
      .catchError(print);


Copy the code

5. 4, and the Future. DoWhile ()

Similar to the Java use of doWhile, repeating an action until false or Future is returned to exit the loop.

  • Usage scenario: Suitable for some scenarios that require recursive operations.

Generate a random number and wait until 10 seconds later, the operation ends.

void futureDoWhile(){
  var random = new Random();
  var totalDelay = 0;
  Future
      .doWhile(() {
    if (totalDelay > 10) {
      print('total delay: $totalDelay seconds');
      return false;
    }
    var delay = random.nextInt(5) + 1;
    totalDelay += delay;
    return new Future.delayed(new Duration(seconds: delay), () {
      print('waited $delay seconds');
      return true;
    });
  })
      .then(print)
      .catchError(print);
}
// Output result:
I/flutter (11113): waited 5 seconds
I/flutter (11113): waited 1 seconds
I/flutter (11113): waited 3 seconds
I/flutter (11113): waited 2 seconds
I/flutter (11113): total delay: 12 seconds
I/flutter (11113) :null


Copy the code

5. 5, microtask

Future.microtask(FutureOr computation())

Create a Future that runs on a MicroTask queue.

This will require you to know the priority main > MicroTask > Event

Microtasks take precedence over Events

Future((){
  print("Future event 1");
});
Future((){
  print("Future event 2");
});
Future.microtask((){
 print("microtask event");
});
// Output the result
//microtask event
//Future event 1
//Future event 2


Copy the code

So here we go. Good night

Originally read some articles, always write to feel laborious reading. This article has referred to two articles, now listed separately, thanks to the author.


Reference:

Flutter | event loop, the Future juejin. Cn/post / 702699…

[Flutter]Dart Future details juejin.cn/post/684490…