如何确保产品接口请求完成后再执行产品类型接口请求并处理数据?
问题描述
我开发了一款应用,需要调用两个接口:一个拉取产品列表,另一个拉取产品类型列表。第二个接口仅返回类型列表,但我需要在该列表开头添加“All”类型,并附上产品总数。
预期流程:
- 调用产品列表接口,返回所有产品的JSON数据
- 调用产品类型列表接口,返回所有类型数据
待类型数据返回后,要在列表开头添加“All”类型并统计产品总数,因此必须确保第一个接口请求完成后再处理第二个接口的结果。
当前初始化代码:
private var listOfProducts: List<Product> = emptyList() private var listOfTypes: List<Type> = emptyList() private var selectedType: String = "" init { fetchProducts() fetchTypes() }
请求方法实现:
fun fetchProducts() { viewModelScope.launch { API_CALL { listOfProducts = response } } }
fun fetchTypes() { viewModelScope.launch { API_CALL { val nbProducts = listOfProducts.count() listOfTypes = Type("all", nbProducts) + response } } }
由于网络延迟,fetchTypes中使用listOfProducts计数时可能失败,因为产品请求尚未完成。需要实现:要么阻止fetchTypes触发直到fetchProducts完成,要么同时发起两个请求,但等待前者完成后再处理后者的数据。
方案一:串行请求(先完成产品拉取,再发起类型请求)
调整初始化逻辑,让类型请求在产品请求完成后再执行,确保产品数据已就绪:
修改后的代码:
private var listOfProducts: List<Product> = emptyList() private var listOfTypes: List<Type> = emptyList() private var selectedType: String = "" init { fetchProductsAndThenTypes() } private fun fetchProductsAndThenTypes() { viewModelScope.launch { // 先执行产品接口请求,确保数据写入listOfProducts API_CALL { listOfProducts = response } // 产品数据就绪后,发起类型请求并处理结果 API_CALL { val nbProducts = listOfProducts.count() listOfTypes = Type("all", nbProducts) + response } } }
也可以拆分保留原方法,将请求改为挂起函数,保证执行顺序:
init { viewModelScope.launch { fetchProducts() fetchTypes() } } private suspend fun fetchProducts() { API_CALL { listOfProducts = response } } private suspend fun fetchTypes() { API_CALL { val nbProducts = listOfProducts.count() listOfTypes = Type("all", nbProducts) + response } }
这种方式逻辑直观,完全避免竞态问题,适合对请求顺序要求明确的场景。
方案二:并行发起请求,等待产品结果后处理类型数据
同时发起两个接口请求提升整体效率,等待产品请求完成后,再结合类型数据处理:
private var listOfProducts: List<Product> = emptyList() private var listOfTypes: List<Type> = emptyList() private var selectedType: String = "" init { fetchDataInParallel() } private fun fetchDataInParallel() { viewModelScope.launch { // 同时发起两个异步请求 val productsDeferred = async { API_CALL { response } // 直接返回产品列表结果 } val typesDeferred = async { API_CALL { response } // 直接返回类型列表结果 } // 先等待产品请求完成,拿到产品数据 val products = productsDeferred.await() listOfProducts = products // 再获取类型数据,结合产品总数生成最终类型列表 val types = typesDeferred.await() val nbProducts = products.count() listOfTypes = Type("all", nbProducts) + types } }
这种方式两个接口同时请求,减少整体等待时间,同时保证处理类型数据时产品总数已就绪。
内容的提问来源于stack exchange,提问作者Seb
相关产品推荐
相关产品推荐

