场景描述:

ajax设置timeout在本机测试有效,但是在生产环境等外网环境无效的问题

 

1.ajax的timeout属性设置 前端请求超时事件【网络连接不稳定时候,就无效了】

var data = JSON字符串;

$.ajax({

type: "POST",

url: url,

dataType: 'json',

timeout: 3000,//3s钟超时

data: data,

xhrFields: {

withCredentials: true

},

success: function (json) {

alert("保存成功")

},

error: function (err, textStatus, errorThrown) {

alert("保存失败")

}

});

 

属性说明:

timeout: //单位是毫秒值

timeout: 0 //代表永不超时

 

其他说明:

当然,ajax里面设置的是前端超时事件,后端服务 的接口 也有超时时间。

声明: timeout属性设置的超时时间,肯定是有效果的。

但是 在生产环境等时候,因为网络跳动不稳定,导致 前后端连接中断了,即使这里的超时时间设置再大 或者设置永不超时,也会进入error,即会发生超时情况。这种时候,就需要 在前端使用轮询去解决这种问题了。

 

 

 

2.spring boot为例,设置接口超时时间的两种方式

 

1> 在配置文件application.properties中加了spring.mvc.async.request-timeout=20000,意思是设置超时时间为20000ms即20s,

2>还有一种就是在config配置类中加入

public class WebMvcConfig extends WebMvcConfigurerAdapter {

@Override

public void configureAsyncSupport(final AsyncSupportConfigurer configurer) {

configurer.setDefaultTimeout(20000);

configurer.registerCallableInterceptors(timeoutInterceptor());

}

@Bean

public TimeoutCallableProcessingInterceptor timeoutInterceptor() {

return new TimeoutCallableProcessingInterceptor();

}

}

 

 

 

 

3.前端轮询方案 ,查询后端的保存状态,直到查询到后端的保存状态为成功,才做相应的用户响应操作 【解决ajax设置timeout避免不了的网络不稳定的问题】

轮询方案简介:

这里就要对 1中的 ajax进行改造了 。

这里使用 js的 setInterval()发起轮询 clearInterval()停止轮询

setInterval(code,millisec)

参数 描述

code 必需。要调用的函数或要执行的代码串。

millisec 必须。周期性执行或调用 code 之间的时间间隔,以毫秒计。

setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。

setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。

 

轮询方案代码:

var data = JSON字符串;

var myFlag = new Date().getTime(); //作为本次保存的 唯一标识

data.myFlag = myFlag; //作为后端入参传给后台

$.ajax({

type: "POST",

url: url,

dataType: 'json',

timeout: 0,//永不超时

data: data,

xhrFields: {

withCredentials: true

},

success: function (json) {

alert("处理成功的逻辑 依旧写在这里");

},

error: function (err, textStatus, errorThrown) {

//此处要判断 error时候,是不是因为超时导致的,如果是超时导致的error,那就做轮询

if (textStatus == 408 || textStatus == 'timeout') {

//轮询查询批量保存状态

window.myFlag2222 = setInterval(function (){

this.batchSaveTimer(myFlag);

},6000);

}else {

loading.hide();

$('.J_button_submit').prop('disabled', false);

tips.show("保存失败");

}

}

});

batchSaveTimer: function (flag) {

$.ajax({

type:'get',

url: url + "/" + flag,

dataType:'json',

cache:true,

xhrFields: {

withCredentials: true

},

success:function(result) {

if (result.code && result.code == 'success' ) {

//当后端保存状态为1 代表保存成功

if (result.data == '1') {

//这里就 停止轮询 入参一定是 发起轮询的setInterval()方法的返回值

clearInterval(window.myFlag2222);

alert("这里同样写一份 处理成功的逻辑");

//当后端保存状态为-1 代表保存失败

} else if (result.data == '-1') {

//这里视业务而定,是否停止轮询

clearInterval(window.myFlag2222);

alert("这里写一份 处理失败的逻辑");

}

}

},

error:function() {

alert("服务器异常")

}

});

},

 

附录说明:

当然,后端处理也很简单,在redis记录一个 status.

myFlag作为key

status作为value

开始保存,把status设置为0 开始处理

status设置为1 处理成功

status设置为-1 处理失败

 

查看原文