原生JS代码实现无痛刷新Token、RefreshToken

1,778 阅读1分钟

背景:项目中用到第三方接口,第三方认证机制要求数据请求中带上token认证。token有效时间是30分钟,refreshtoken有效时间30天。token过期,需要用refreshtoken重新获取。面临问题:如果token已失效,此时页面发送多个数据请求,为保证token有效,可能需要重复发送多个冗余token请求。

       前两天有人写过获取方案,但是是基于axios实现的,我们的项目使用的是原生fetch、promise,不可能为了这个适配再专门引入axios,故自己抽时间实现了一个原生版的。

       主要思想就是封装请求接口,每一个数据请求发起之前先检测token是否不存在或已过期。token无效时,发起token获取请求,这期间的数据请求都先缓存在promise中。待到token刷新后,再一一处理。

var isLoading = false;
var isTokenInvalid = false;
var promise = null;

// 暴露给外部的接口
function post(api) {
	// 正在加载token, 且还没有生成promise
	if (isLoading === true) {
		return promise.then(() => {
			// 此处一定要return promise
			return request(api)
		})
	} else if (!isTokenInvalid) {
		// 还没有生成token
		promise = new Promise((resolve, reject) => {
			isLoading = true;
                        // 模拟token获取函数
			setTimeout(() => {
				token = 12;
				console.log('生成token')
				isTokenInvalid = true;
				isLoading = false;
				resolve();
			}, 2000);
		});
		return promise.then(() => {
			return request(api)
		});
	} else {
		return request(api);
	}
}

// 内部函数
function request(api) {
	return new Promise((resolve) => {
                // 模拟数据请求接口
		setTimeout(() => {
			console.log('result:' + api + ' ' + new Date().toLocaleString())
			resolve(api + '请求结果');
		}, 5000)
	});
}

// 测试函数
function test() {
	Promise.all([post('api1'), post('api2')]).then((res) => {
		console.log(res)
	})
}
test();