请求执行顺序异常:如何确保第二个请求在第一个请求成功后发起?
解决请求重复触发的问题
看起来你遇到了个有点头疼的请求重复调用问题——明明预期第一个请求的onSuccess先执行,结果Context.getAlarmGroupChainById直接被调用了两次,甚至第二个请求还抢在了回调前面。我来帮你梳理下可能的原因和解决办法:
可能的触发原因
loadAll函数被重复调用了:这是最常见的情况,比如页面初始化时(Angular的路由resolve、组件$onInit钩子、ng-init指令)这个函数被触发了两次,导致整个请求逻辑执行了两遍。- 封装的请求方法内部有重复逻辑:
Context.getAlarmGroupChainById这个自定义方法里可能不小心写了两次请求调用,或者默认开启了重试机制,导致一次调用实际发了两次HTTP请求。 - 异步流程的意外并发:如果
loadAll被触发两次的时机非常接近,两个请求会同时发起,自然不会等第一个的onSuccess执行完再发第二个。
排查与解决步骤
1. 先确认函数的调用次数
先给loadAll加个日志,看看它是不是真的被执行了两次:
function loadAll () { console.log('loadAll 执行了,时间戳:', Date.now()); // 新增日志 Context.getAlarmGroupChainById({ id: $stateParams.id }, onSuccess, onError); function onSuccess(data, headers) { vm.temp=data; var numberGroupChain=vm.temp.length; for(var i=0; i<numberGroupChain; i++){ vm.location.push(vm.temp[i].location); // ... 你的后续逻辑 } } function onError(err) { // 错误处理 } }
如果控制台输出了两条日志,那就要去查loadAll的触发源:
- 检查路由配置:是不是路由的
resolve里重复引用了这个方法? - 检查组件/控制器:是不是用了
ng-controller指令的同时,又在路由里指定了控制器,导致控制器被实例化两次? - 检查生命周期钩子:比如Angular 1.x的
$onInit是不是被触发了两次(比如组件被重复渲染)?
2. 检查请求封装方法的内部实现
如果loadAll只执行了一次,但请求还是发了两次,那就要看Context.getAlarmGroupChainById的源码:
- 是不是内部调用了两次
$http或者其他请求库? - 有没有默认的重试逻辑?比如请求失败后自动重试,但第一次请求其实没失败就触发了重试?
- 有没有监听某些事件导致重复发起请求?
3. 临时添加请求锁(快速解决)
如果暂时找不到根源,可以先加个锁机制,防止同一时间发起重复请求:
function loadAll () { if (vm.isLoading) return; // 如果正在加载,直接返回,不重复发起请求 vm.isLoading = true; Context.getAlarmGroupChainById({ id: $stateParams.id }, function(data, headers) { vm.isLoading = false; // 请求成功后解锁 vm.temp=data; var numberGroupChain=vm.temp.length; for(var i=0; i<numberGroupChain; i++){ vm.location.push(vm.temp[i].location); // ... 你的后续逻辑 } }, function(err) { vm.isLoading = false; // 请求失败也要解锁,避免后续无法发起请求 // 错误处理逻辑 }); }
这个方法能快速阻止重复请求,同时你可以继续排查根本原因。
另外,也可以留意下$stateParams.id是不是有变化?如果这个参数在请求发起前后被修改了,也可能导致看起来像两次请求,但你描述的是同一个方法被调用两次,大概率不是这个情况。
内容的提问来源于stack exchange,提问作者Belhanda
相关产品推荐
相关产品推荐

