Dart中的异步操作总结

Dart类库有非常多的返回Future或者Stream对象的函数,这些函数被称为异步函数。

1. Future

Future与JavaScript中的Promise非常相似,表示一个异步操作的最终完成(或失败)及其结果值的表示。异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。一个Future只会对应一个结果,要么成功,要么失败。

还有,Future 的所有API的返回值仍然是一个Future对象。
1)Future.then
为了方便示例,在本例中我们使用Future.delayed 创建了一个延时任务(实际场景会是一个真正的耗时任务,比如一次网络请求),即2秒后返回结果字符串"hi world!",然后我们在then中接收异步结果并打印结果,代码如下:

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

2)Future.catchError
如果异步任务发生错误,我们可以在catchError中捕获错误,我们将上面示例改为:

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

在本例中,我们在异步任务中抛出了一个异常,then的回调函数将不会被执行, catchError回调函数将被调用;但是,并不是只有 catchError回调才能捕获错误,then方法还有一个可选参数onError,我们也可以用它来捕获异常:

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

3)Future.whenComplete
有些时候,我们会遇到无论异步任务执行成功或失败都需要做一些事的场景,比如:在网络请求前弹出加载对话框,在请求结束后关闭对话框,这种场景,有两种方法:

1.分别在then或catch中关闭一下对话框
2.使用Future的whenComplete回调

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

4)Future.wait
有些时候,我们需要等待多个异步任务都执行结束后才进行一些操作,比如我们有一个界面,需要先分别从两个网络接口获取数据,获取成功后,我们需要将两个接口数据进行特定的处理,再显示到UI界面上,这时可以用Future.wait,它接受一个Future数组参数,只有数组中所有Future都执行成功后,才会触发then的成功回调,只要有一个Future执行失败,就会触发错误回调。

  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);
  });

执行上面代码,4秒后你会在控制台中看到“hello world”。

2.async/await

正如上文所述, “Future 的所有API的返回值仍然是一个Future对象” ,如果在then 中返回的是一个Future的话,该future会执行,执行结束后会触发后面的then回调,这样依次向下,就避免了层层嵌套。

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

Dart中的async/await的意思就是:异步任务串行化,可以避免我们在使用过程中遇到的回调地狱问题。

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

3.Stream

Stream也是用于接收异步事件数据,和 Future不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。

  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: () {
    
    });

上面的代码依次会输出:

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

猜你喜欢

转载自blog.csdn.net/qq_36162336/article/details/129816249