Use fetch instead of jQuery
This commit is contained in:
parent
5cb1decfac
commit
752ee78c49
5 changed files with 78 additions and 51 deletions
|
@ -1,4 +1,4 @@
|
|||
import { to, getJSON } from '@utils';
|
||||
import { getJSON } from '@utils';
|
||||
|
||||
export default class OperationsQueue {
|
||||
constructor(baseUrl) {
|
||||
|
@ -30,23 +30,27 @@ export default class OperationsQueue {
|
|||
async exec(operation) {
|
||||
const { path, method, payload, resolve, reject } = operation;
|
||||
const url = `${this.baseUrl}${path}`;
|
||||
const [data, xhr] = await to(getJSON(url, payload, method));
|
||||
|
||||
if (xhr) {
|
||||
handleError(xhr, reject);
|
||||
} else {
|
||||
try {
|
||||
const data = await getJSON(url, payload, method);
|
||||
resolve(data);
|
||||
} catch (e) {
|
||||
handleError(e, reject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleError(xhr, reject) {
|
||||
try {
|
||||
const {
|
||||
errors: [message]
|
||||
} = JSON.parse(xhr.responseText);
|
||||
async function handleError({ response, message }, reject) {
|
||||
if (response) {
|
||||
try {
|
||||
const {
|
||||
errors: [message]
|
||||
} = await response.json();
|
||||
reject(message);
|
||||
} catch {
|
||||
reject(await response.text());
|
||||
}
|
||||
} else {
|
||||
reject(message);
|
||||
} catch (e) {
|
||||
reject(xhr.responseText);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import jQuery from 'jquery';
|
|||
|
||||
import '../shared/page-update-event';
|
||||
import '../shared/activestorage/ujs';
|
||||
import '../shared/rails-ujs-fix';
|
||||
import '../shared/safari-11-file-xhr-workaround';
|
||||
import '../shared/remote-input';
|
||||
import '../shared/franceconnect';
|
||||
|
|
|
@ -7,7 +7,6 @@ import ReactRailsUJS from 'react_ujs';
|
|||
import '../shared/page-update-event';
|
||||
import '../shared/activestorage/ujs';
|
||||
import '../shared/remote-poller';
|
||||
import '../shared/rails-ujs-fix';
|
||||
import '../shared/safari-11-file-xhr-workaround';
|
||||
import '../shared/remote-input';
|
||||
import '../shared/franceconnect';
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
import jQuery from 'jquery';
|
||||
|
||||
// rails-ujs installs CSRFProtection for its own ajax implementation. We might need
|
||||
// CSRFProtection for jQuery initiated requests. This code is from jquery-ujs.
|
||||
jQuery.ajaxPrefilter((options, originalOptions, xhr) => {
|
||||
if (!options.crossDomain) {
|
||||
CSRFProtection(xhr);
|
||||
}
|
||||
});
|
||||
|
||||
function csrfToken() {
|
||||
return jQuery('meta[name=csrf-token]').attr('content');
|
||||
}
|
||||
|
||||
function CSRFProtection(xhr) {
|
||||
let token = csrfToken();
|
||||
if (token) {
|
||||
xhr.setRequestHeader('X-CSRF-Token', token);
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
import Rails from '@rails/ujs';
|
||||
import $ from 'jquery';
|
||||
import debounce from 'debounce';
|
||||
|
||||
export { debounce };
|
||||
export const { fire } = Rails;
|
||||
export const { fire, csrfToken } = Rails;
|
||||
|
||||
export function show(el) {
|
||||
el && el.classList.remove('hidden');
|
||||
|
@ -67,17 +66,20 @@ export function ajax(options) {
|
|||
});
|
||||
}
|
||||
|
||||
export function getJSON(url, data, method = 'get') {
|
||||
data = method !== 'get' && data ? JSON.stringify(data) : data;
|
||||
return Promise.resolve(
|
||||
$.ajax({
|
||||
method,
|
||||
url,
|
||||
data,
|
||||
contentType: 'application/json',
|
||||
dataType: 'json'
|
||||
})
|
||||
);
|
||||
export function getJSON(url, data, method = 'GET') {
|
||||
const { query, ...options } = fetchOptions(data, method);
|
||||
|
||||
return fetch(`${url}${query}`, options).then((response) => {
|
||||
if (response.ok) {
|
||||
if (response.status === 204) {
|
||||
return null;
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
const error = new Error(response.statusText || response.status);
|
||||
error.response = response;
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
export function scrollTo(container, scrollTo) {
|
||||
|
@ -95,10 +97,6 @@ export function on(selector, eventName, fn) {
|
|||
);
|
||||
}
|
||||
|
||||
export function to(promise) {
|
||||
return promise.then((result) => [result]).catch((error) => [null, error]);
|
||||
}
|
||||
|
||||
export function isNumeric(n) {
|
||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||
}
|
||||
|
@ -120,3 +118,50 @@ export function timeoutable(promise, timeoutDelay) {
|
|||
});
|
||||
return Promise.race([promise, timeoutPromise]);
|
||||
}
|
||||
|
||||
const FETCH_TIMEOUT = 30 * 1000; // 30 sec
|
||||
|
||||
function fetchOptions(data, method = 'GET') {
|
||||
const options = {
|
||||
query: '',
|
||||
method: method.toUpperCase(),
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
'x-csrf-token': csrfToken(),
|
||||
'x-requested-with': 'XMLHttpRequest'
|
||||
},
|
||||
credentials: 'same-origin'
|
||||
};
|
||||
|
||||
if (data) {
|
||||
if (options.method === 'GET') {
|
||||
options.query = objectToQuerystring(data);
|
||||
} else {
|
||||
options.headers['content-type'] = 'application/json';
|
||||
options.body = JSON.stringify(data);
|
||||
}
|
||||
}
|
||||
|
||||
if (window.AbortController) {
|
||||
const controller = new AbortController();
|
||||
options.signal = controller.signal;
|
||||
|
||||
setTimeout(() => {
|
||||
controller.abort();
|
||||
}, FETCH_TIMEOUT);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function objectToQuerystring(obj) {
|
||||
return Object.keys(obj).reduce(function (query, key, i) {
|
||||
return [
|
||||
query,
|
||||
i === 0 ? '?' : '&',
|
||||
encodeURIComponent(key),
|
||||
'=',
|
||||
encodeURIComponent(obj[key])
|
||||
].join('');
|
||||
}, '');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue