$ .ajax beforeSend不等待其他ajax请求

时间:2018-07-17 09:49:28

标签: javascript jquery ajax asynchronous xmlhttprequest

我有一个带有refreshToken的jwt身份验证系统。 客户端浏览器每隔5分钟必须请求一个新的accessToken,并将其refreshToken保存在localStorage中。

为此,我在每次AJAX调用中都使用了“发送前”功能。

$.ajaxSetup({
    beforeSend: addAuthHeader,
});

function addAuthHeader(xhr) {
   if(Math.round(new Date() / 1000) >= sessionStorage.getItem('jwt_exp')) {
        console.log('JWT expired. Refreshing now...');
        $.ajax({
            method: 'POST',
            url: '/auth/token/refresh',
            beforeSend: function (xhr) { },
            data: { token: localStorage.getItem('refreshToken') },
            // TODO: FIXME:  Synchronous are deprected
            async: false,
        }).done(function (data) {
            sessionStorage.setItem('jwt', data.accessToken);
            sessionStorage.setItem('jwt_exp', data.exp);

            xhr.setRequestHeader('Authorization', 'Bearer ' + data.accessToken);
            console.log('Authorization', 'Bearer ' + data.accessToken);
        });
    } else {
        xhr.setRequestHeader('Authorization', 'Bearer ' + sessionStorage.getItem('jwt'));
        console.log('Authorization', 'Bearer ' + sessionStorage.getItem('jwt'));
    }
}

如您所见,我现在正在使用同步请求。 但是这些已被弃用:

[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

我能做些我想做的异步事情吗?
运行第二个ajax调用不会更改Headers =>,直到一切都完成之前,SendSend不等待

3 个答案:

答案 0 :(得分:1)

在发送请求之前立即触发beforeSend属性,但是请求不会等待它完成。这是设计使然。

要创建您的功能,我会将您的请求包装在一个特殊的函数中,将要发送的请求放在addAuthHeader请求的.done函数中。

类似的东西:

function sendRequestWithAuth(requestFunction) {
   if(Math.round(new Date() / 1000) >= sessionStorage.getItem('jwt_exp')) {
        console.log('JWT expired. Refreshing now...');
        $.ajax({
            method: 'POST',
            url: '/auth/token/refresh',
            beforeSend: function (xhr) { },
            data: { token: localStorage.getItem('refreshToken') },
            // TODO: FIXME:  Synchronous are deprected
            async: false,
        }).done(function (data) {
            sessionStorage.setItem('jwt', data.accessToken);
            sessionStorage.setItem('jwt_exp', data.exp);

            xhr.setRequestHeader('Authorization', 'Bearer ' + data.accessToken);
            console.log('Authorization', 'Bearer ' + data.accessToken);
            requestFunction();
        });
    } else {
        xhr.setRequestHeader('Authorization', 'Bearer ' + sessionStorage.getItem('jwt'));
        console.log('Authorization', 'Bearer ' + sessionStorage.getItem('jwt'));
        requestFunction();
    }
}

这将确保在执行插入到requestFunction()回调中的任何函数之前,发送并接收您的刷新请求。

要传递xhr.setRequestHeader,您可以将{作为参数传递给requestFunction,例如:requestFunction(data.accessToken);requestFunction(sessionStorage.getItem('jwt'));,然后将值插入到函数内部的请求中。

答案 1 :(得分:0)

您在代码中使用的JQuery [async:false]属性已过时。

尝试使用异步/等待功能并像这样调用ajax:

async function fun() {
    ...
    await $.ajax({
        ...

对我有用。

答案 2 :(得分:0)

另一个选择是取消您在@Component({}) export abstract class AbstractBaseComponent { @ViewChild('test') public testRef: TestComponent; } 内的请求(通过返回beforeSend)并使用新的标头创建一个新请求。例如,这对我有用,并自动应用于我的所有请求,而无需调用任何包装器:

false