在done回调中无法直接判断HTTP 401,因layui只传响应体;应检查res.code是否为约定登出码(如401),或改用url函数+$.ajax手动捕获xhr.status === 401。
table.reload 的 done 回调里怎么判断 401
layui 的 table.reload 不会把 http 状态码(如 401)直接透传给 done,它只处理响应体。所以不能靠 res.status === 401 判断——这个字段根本不存在于 done 的参数里。
真正能用的,是后端在响应体中返回的业务码(比如 code: 401)或自定义字段。前提是后端配合,在鉴权失败时仍返回 200 状态 + 业务错误结构,例如:{"code":401,"msg":"登录已过期","data":null}。
- 检查
done中的res.code是否等于你约定的登出码(如401或"unauthorized"),而不是依赖 HTTP 状态 - 如果后端坚持用真实 HTTP 401 响应(不返回 JSON),那
done根本不会执行,必须改用url配函数 +$.ajax手动捕获 - 别在
done里直接跳转,先layer.msg提示,再setTimeout延迟跳转,避免用户操作中断
url 配成函数后如何捕获原生 401 网络错误
当后端返回真实 HTTP 401(非 200)时,layui 默认不进任何回调。唯一可靠方式是把 url 设为函数,内部用 $.ajax 或 fetch 发请求,并在 error 或 catch 中兜底。
示例写法(jQuery):
url: function (obj) {
$.ajax({
url: '/api/list',
type: 'GET',
headers: { 'Authorization': 'Bearer ' + localStorage.token },
dataType: 'json',
success: function (res) {
obj.done(res); // 正常走 layui 渲染流程
},
error: function (xhr, status, err) {
if (xhr.status === 401) {
layer.msg('登录已过期,请重新登录', { icon: 7 });
setTimeout(function () {
location.href = '/login';
}, 1500);
} else {
layer.msg('请求异常:' + err, { icon: 2 });
}
}
});
}
- 必须调用
obj.done()传入伪造或默认数据,否则表格卡在 loading 状态 -
headers要动态读取,比如从localStorage.token,不能写死字符串 - 别漏掉
dataType: 'json',否则xhr.responseJSON可能为 undefined
全局拦截所有 table 请求的 401(含 reload)
只要所有请求都走 layui.jquery.ajax(table、form、admin.req 默认都走它),就可以用 $.ajaxPrefilter 统一加头 + 用 $.ajaxSetup 的 complete 拦截状态码 —— 但注意:$.ajaxSetup 在部分 Layui 1.x 版本中失效,优先用 ajaxPrefilter + ajaxComplete 组合。
推荐写法:
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
var token = localStorage.token;
if (token) {
options.headers = options.headers || {};
options.headers['Authorization'] = 'Bearer ' + token;
}
});
$(document).ajaxComplete(function (event, xhr, settings) {
if (xhr.status === 401 && settings.url.indexOf('/api/') > -1) {
layer.msg('身份验证失效', { icon: 7 });
setTimeout(function () {
location.href = '/login';
}, 1200);
}
});
-
ajaxComplete会拦截所有请求,所以加了settings.url.indexOf('/api/')过滤,避免误杀静态资源 - 该方案对
table.reload也生效,因为 reload 底层仍是 ajax - 如果用了
contentType: 'application/json',确保headers里也带上了,否则某些后端中间件会忽略认证头
为什么 reload 后没触发 401 处理逻辑
最常见原因是:reload 时没重传 headers。table.render 初始化时传的 headers 不会自动继承到 reload 中,每次 reload 都得显式带上。
- 错误写法:
table.reload('id')—— 没传任何配置,headers 丢失,后端收不到 token,返回 401,但前端没拦截逻辑 - 正确写法:
table.reload('id', { headers: { Authorization: 'Bearer ' + localStorage.token } }) - 如果用的是
url函数方式,则 reload 时仍会走那个函数,headers 由函数内部控制,reload 参数里可不传 headers - 高频刷新场景下,401 可能被节流逻辑跳过 —— 检查是否在上一次请求未完成时就 abort 了本次,导致 error 回调没执行
headers,以及以为 done 能拿到 HTTP 状态码。这两个点没踩准,401 就永远静默失败。











