Summary of asynchronous operations in Dart

The Dart class library has a lot of functions that return Future or Stream objects. These functions are called asynchronous functions.

1. Future

A Future is very similar to a Promise in JavaScript, representing the eventual completion (or failure) of an asynchronous operation and the representation of its result value. If the asynchronous processing succeeds, the successful operation is executed, and if the asynchronous processing fails, the error is caught or the subsequent operation is stopped. A Future will only correspond to one result, either success or failure.

Also, the return value of all Future APIs is still a Future object.
1) Future.then
For the convenience of the example, in this example we use Future.delayed to create a delayed task (the actual scenario will be a real time-consuming task, such as a network request), that is, return the result string after 2 seconds "hi world!", then we receive the asynchronous result in then and print the result, the code is as follows:

  Future.delayed(const Duration(seconds: 2), () {
    
    
    return "hi world";
  }).then((value) => print(value));

2) Future.catchError
If an error occurs in the asynchronous task, we can catch the error in catchError, we change the above example to:

  Future.delayed(const Duration(seconds: 2), () {
    
    
    //return "hi world!";
    throw AssertionError("Error");
  }).then((data) {
    
    
    //执行成功会走到这里
    print("success");
  }).catchError((e) {
    
    
    //执行失败会走到这里
    print(e);
  });

In this example, we throw an exception in the asynchronous task, the callback function of then will not be executed, and the callback function of catchError will be called; however, it is not only the callback of catchError that can catch errors, the then method also has a Optional parameter onError, we can also use it to catch exceptions:

  Future.delayed(const Duration(seconds: 2), () {
    
    
    //return "hi world!";
    throw AssertionError("Error");
  }).then((data) {
    
    
    print("success");
  }, onError: (e) {
    
    
    print(e);
  });

3) Future.whenComplete
Sometimes, we will encounter scenarios where we need to do something regardless of the success or failure of the asynchronous task execution, such as: a loading dialog box pops up before the network request, and the dialog box is closed after the request ends. In this scenario, There are two methods:

1. Close the dialog box in then or catch respectively.
2. Use Future's whenComplete callback

Future.delayed(const Duration(seconds: 2), () {
    
    
    //return "hi world!";
    throw AssertionError("Error");
  }).then((data) {
    
    
    //执行成功会走到这里
    print(data);
  }).catchError((e) {
    
    
    //执行失败会走到这里
    print(e);
  }).whenComplete(() {
    
    
    //无论成功或失败都会走到这里
  });

4) Future.wait
Sometimes, we need to wait for multiple asynchronous tasks to be executed before performing some operations. For example, if we have an interface, we need to obtain data from two network interfaces first. After the acquisition is successful, we need to transfer the two The interface data is processed in a specific way, and then displayed on the UI interface. At this time, Future.wait can be used, which accepts a Future array parameter. Only after all the Futures in the array are successfully executed, the success callback of then will be triggered. As long as there is one If the Future execution fails, an error callback will be triggered.

  Future.wait([
    // 2秒后返回结果
    Future.delayed(const Duration(seconds: 2), () {
    
    
      return "hello";
    }),
    // 4秒后返回结果
    Future.delayed(const Duration(seconds: 4), () {
    
    
      return "world";
    })
  ]).then((result) {
    
    
    print(result[0] + result[1]);
  }).catchError((e) {
    
    
    print(e);
  });

Execute the above code, and you will see "hello world" in the console after 4 seconds.

2.async/await

As mentioned above, "the return value of all Future APIs is still a Future object", if a Future is returned in then, the future will be executed, and the subsequent then callback will be triggered after the execution, so that Next, layers of nesting are avoided.

login("alice","******").then((id){
    
    
  	return getUserInfo(id);
}).then((userInfo){
    
    
    return saveUserInfo(userInfo);
}).then((e){
    
    
   //执行接下来的操作 
}).catchError((e){
    
    
  //错误处理  
  print(e);
});

The meaning of async/await in Dart is: the serialization of asynchronous tasks can avoid the callback hell problem we encounter during use.

task() async {
    
    
	try {
    
    
		String? id = await login("admin", "xxx");
		String? userInfo = await getUserInfo(id!);
		await saveUserInfo(userInfo!);
		//执行接下来的操作 
	} catch(e) {
    
    
		//错误处理
		print(e);
	}
}

3.Stream

Stream is also used to receive asynchronous event data. Unlike Future, it can receive the results of multiple asynchronous operations (success or failure). That is, when executing an asynchronous task, success or failure events can be fired multiple times to deliver result data or error exceptions.

  Stream.fromFutures([
    // 1秒后返回结果
    Future.delayed(const Duration(seconds: 1), () {
    
    
      return "hello 1";
    }),
    // 抛出一个异常
    Future.delayed(const Duration(seconds: 2), () {
    
    
      throw AssertionError("Error");
    }),
    // 3秒后返回结果
    Future.delayed(const Duration(seconds: 3), () {
    
    
      return "hello 3";
    })
  ]).listen((data) {
    
    
    print(data);
  }, onError: (e) {
    
    
    print(e.message);
  }, onDone: () {
    
    });

The above code in turn will output:

2023-03-28 15:12:10.356  6222-6280  flutter                 com.example.hello_flutter            I  hello 1
2023-03-28 15:12:11.364  6222-6280  flutter                 com.example.hello_flutter            I  Error
2023-03-28 15:12:12.354  6222-6280  flutter                 com.example.hello_flutter            I  hello 3

Guess you like

Origin blog.csdn.net/qq_36162336/article/details/129816249