Skip to content

回调地狱

如果代码中有大量的异步逻辑,并且这些请求有先后关系,可能后一个请求需要用到前一个请求的返回结果,那么就会出现**回调地狱,**例如用户登录的场景,首先需要用户登录,用户登录成功可以获得用户的id。通过用户的Id可以再去请求用户的个人信息,获得个人信息;为了使用的方便,我们一般还会把个人信息缓存在本地文件中,那么代码就会变成这样

java
//先分别定义各个异步任务
Future<String> login(String userName, String pwd){
	...
    //用户登录
};
Future<String> getUserInfo(String id){
	...
    //获取用户信息 
};
Future saveUserInfo(String userInfo){
	...
	// 保存用户信息 
}; 

//回调地狱
login("alice","******").then((id){
 //登录成功后通过,id获取用户信息    
 getUserInfo(id).then((userInfo){
    //获取用户信息后保存 
    saveUserInfo(userInfo).then((){
       //保存用户信息,接下来执行其他操作
        ...
    });
  });
})

如何解决回调地狱呢?

Future的链式调用

可以使用Future的链式调用来消除,Future 的所有API的返回值仍然是一个Future对象。所以在调用then之后返回的结果还是一个Future,前一个then执行结束,就会触发后面的then回调,如此向下,避免了嵌套

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

async/await

我们直到在kotlin中可以以编写同步代码的形式来执行异步任务,这大大的增加了代码的可读性,那么Dart是否支持呢?当然也是可以的。利用async和await,例如如下代码: async:用来表示函数(用于修饰函数)是异步的,它会返回一个Future对象 await:修饰的是一个Future,表示等待该异步任务完成,才会往后执行,注意await必须出现在async内部

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