问题描述
封装一个基于 jQuery 的 AJAX 请求中,需要在某些请求(如 “/user/voteuserlogin” 和 “/user/uvote”)中进行登录检查。如果用户未登录或者登录的 token 已过期,需要让用户重新登录。然而,遇到了一个问题:在用户登录后,无法继续执行原来的请求。
原因分析:
这个问题的原因在于 AJAX 请求是异步的,登录检查是同步的。当我们检查到用户未登录或 token 过期时,我们会尝试重新登录,但是这个登录操作是异步的,所以它不会立即完成。因此,代码会在登录操作完成之前就继续执行,这就导致了我无法在用户登录后继续执行原来的请求。
修改后的代码:
function loginAndSetToken(callback) {
// 这里调用了一个用于检查用户登录状态的函数
checkUserLogin().then(res => {
userInfo.username = res.userInfo.nick_name;
userInfo.id = res.userInfo.openid;
var headers = {
"Content-Type": "application/json",
"token": localStorage.getItem('token') || "",
}
var settings = {
url: baseurl + "/user/voteuserlogin",
type: "POST",
headers: headers,
data: JSON.stringify(userInfo),
timeout: 0,
success: function(res){
if (res.code == 200) {
localStorage.setItem('token', res.token);
headers.token = localStorage.getItem('token');
if (callback) {
callback();
}
}
},
error: function(error) {
console.error(error);
}
};
$.ajax(settings);
}).catch(err => {
console.log("未登录");
console.log(err);
})
}
function ajaxRequest(url, method, data, callback, isLogin) {
var headers = {
"Content-Type": "application/json",
"token": localStorage.getItem('token') || "",
}
// 检查 JWT token 是否过期
var tokenExpired = checkTokenExpiration();
if ((url == "/user/voteuserlogin" || url == "/user/uvote") && (!isLogin || tokenExpired)) {
console.log("未登录外围");
loginAndSetToken(function() {
ajaxRequest(url, method, data, callback, true);
});
return;
}
var settings = {
url: baseurl + url,
type: method,
headers: headers,
data: data,
timeout: 0,
success: function(response) {
if (callback) {
callback(response);
} else {
console.log(response);
}
},
error: function(error) {
console.error(error);
}
};
$.ajax(settings);
}
技术点:
回调函数
在 JavaScript 中,函数是一等公民,可以作为参数传递给其他函数。在这个问题中,我在 loginAndSetToken 函数中添加了一个回调函数参数,当登录成功后,这个回调函数会被调用。
在 loginAndSetToken 函数中,我添加了一个名为 callback 的参数,这个参数是一个函数。当 loginAndSetToken 函数的登录操作成功后,调用这个 callback 函数。
function loginAndSetToken(callback) {
// ... 登录操作 ...
success: function(res){
if (res.code == 200) {
localStorage.setItem('token', res.token);
headers.token = localStorage.getItem('token');
if (callback) {
callback();
}
}
},
// ...
}
在这个例子中,callback 函数是在 ajaxRequest 函数中定义的,它的作用是再次尝试发送原来的请求。
loginAndSetToken(function() {
ajaxRequest(url, method, data, callback, true);
});
这样,当用户登录成功后,我们就可以继续执行原来的请求了。这是因为 callback 函数中的 ajaxRequest 函数会在 loginAndSetToken 函数的登录操作成功后被调用。
这种使用回调函数的方式可以使我们的代码更加灵活和可重用,因为我们可以根据需要传入不同的回调函数来改变 loginAndSetToken 函数的行为
Promise
checkUserLogin() 返回一个 Promise 对象,这是一种用于处理异步操作的对象。.then() 方法用于指定 Promise 状态变为 resolved 时的回调函数,.catch() 方法用于指定 Promise 状态变为 rejected 时的回调函数。
AJAX
AJAX 是一种在无需重新加载整个网页的情况下,与服务器交换数据并更新部分网页的技术。在这个问题中,我们使用 jQuery 的 $.ajax() 方法发送 AJAX 请求。
JSON Web Token (JWT):
JWT 是一种用于身份验证的 token。在这个问题中,我们将 JWT 存储在 localStorage 中,并在每次发送请求时将其添加到请求头中。
localStorage
localStorage 是一种在浏览器中存储数据的方式。在这个问题中,我们使用 localStorage.setItem() 方法存储 token,使用 localStorage.getItem() 方法获取 token。