// composables/useFetchWithoutRace.js
import { ref } from 'vue';
import axios from 'axios';// 定义一个可复用的 Composition 函数,处理带有竞态控制的异步请求
export function useFetchWithoutRace() {// 定义响应式变量 `latestRequestId`,用于追踪最新请求的标识const latestRequestId = ref(null);// 定义异步请求函数,接收 AJAX 配置对象,返回请求结果const fetchWithoutRace = async (ajaxConfig) => {// 生成当前请求的唯一标识,使用时间戳确保每次请求都有不同的 IDconst requestId = Date.now();// 更新 `latestRequestId`,标记这个请求为最新的latestRequestId.value = requestId;try {// 使用传入的 ajaxConfig 发送请求,axios 会根据配置自动处理 method、url、params 等const response = await axios(ajaxConfig);// 检查当前请求的 ID 是否仍然是最新的if (requestId === latestRequestId.value) {// 如果是最新的请求,直接返回响应数据return response.data;}// 如果不是最新的请求,返回 null 或抛出特定标识,避免使用旧数据return null;} catch (error) {// 捕获请求中的错误,抛出以便调用者处理console.error('Fetch error:', error);throw error;}};// 返回 `fetchWithoutRace` 方法,供组件调用return {fetchWithoutRace, // 请求方法,返回 Promise,包含结果或 null};
}
在组件中使用
// 组件代码
<script>
import { ref } from 'vue';
import { useFetchWithoutRace } from '@/composables/useFetchWithoutRace';export default {setup() {// 调用 useFetchWithoutRace,获取 fetchWithoutRace 方法const { fetchWithoutRace } = useFetchWithoutRace();// 定义响应式变量,用于存储结果const result = ref(null);// 定义处理输入的方法,构造 AJAX 配置对象并调用 fetchWithoutRaceconst handleInput = async (value) => {// 创建 AJAX 配置对象const ajaxConfig = {url: '/api/data', // 请求的 API 地址method: 'get', // 请求方法,默认为 GETparams: { q: value }, // 查询参数,传递输入框的值};try {// 调用 fetchWithoutRace,等待结果const data = await fetchWithoutRace(ajaxConfig);// 如果是最新请求,data 会有值;否则为 nullif (data !== null) {result.value = data;}} catch (error) {// 处理请求错误console.log('处理错误:', error);}};// 返回给模板使用的变量和方法return {result, // 请求结果,用于显示handleInput, // 输入处理方法,绑定到输入框};},
};
</script><template><div><!-- 输入框,每次输入时调用 handleInput,传入输入值 --><input @input="handleInput($event.target.value)" placeholder="输入查询" /><!-- 显示请求结果,result 是响应式的,数据更新时自动刷新 --><p>结果: {{ result }}</p></div>
</template>让调用者自己管理结果, fetchWithoutRace 直接返回请求数据。fetchWithoutRace 返回一个 Promise,成功时解析为:
如果是最新请求,返回 response.data。
如果不是最新请求,返回 null。
失败时抛出错误,交给调用者处理。竞态控制:
依然通过 requestId 和 latestRequestId 判断,只有最新请求的结果会被返回。
非最新请求返回 null,避免旧数据干扰。调用者控制结果:
组件中用 await fetchWithoutRace(ajaxConfig) 获取结果,然后手动赋值给 result。