Merge pull request #5682 from tchak/replace-jquery-with-fetch
Use fetch instead of jQuery
This commit is contained in:
commit
2e2086f020
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 {
|
export default class OperationsQueue {
|
||||||
constructor(baseUrl) {
|
constructor(baseUrl) {
|
||||||
|
@ -30,23 +30,27 @@ export default class OperationsQueue {
|
||||||
async exec(operation) {
|
async exec(operation) {
|
||||||
const { path, method, payload, resolve, reject } = operation;
|
const { path, method, payload, resolve, reject } = operation;
|
||||||
const url = `${this.baseUrl}${path}`;
|
const url = `${this.baseUrl}${path}`;
|
||||||
const [data, xhr] = await to(getJSON(url, payload, method));
|
|
||||||
|
|
||||||
if (xhr) {
|
try {
|
||||||
handleError(xhr, reject);
|
const data = await getJSON(url, payload, method);
|
||||||
} else {
|
|
||||||
resolve(data);
|
resolve(data);
|
||||||
|
} catch (e) {
|
||||||
|
handleError(e, reject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleError(xhr, reject) {
|
async function handleError({ response, message }, reject) {
|
||||||
try {
|
if (response) {
|
||||||
const {
|
try {
|
||||||
errors: [message]
|
const {
|
||||||
} = JSON.parse(xhr.responseText);
|
errors: [message]
|
||||||
|
} = await response.json();
|
||||||
|
reject(message);
|
||||||
|
} catch {
|
||||||
|
reject(await response.text());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
reject(message);
|
reject(message);
|
||||||
} catch (e) {
|
|
||||||
reject(xhr.responseText);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import jQuery from 'jquery';
|
||||||
|
|
||||||
import '../shared/page-update-event';
|
import '../shared/page-update-event';
|
||||||
import '../shared/activestorage/ujs';
|
import '../shared/activestorage/ujs';
|
||||||
import '../shared/rails-ujs-fix';
|
|
||||||
import '../shared/safari-11-file-xhr-workaround';
|
import '../shared/safari-11-file-xhr-workaround';
|
||||||
import '../shared/remote-input';
|
import '../shared/remote-input';
|
||||||
import '../shared/franceconnect';
|
import '../shared/franceconnect';
|
||||||
|
|
|
@ -7,7 +7,6 @@ import ReactRailsUJS from 'react_ujs';
|
||||||
import '../shared/page-update-event';
|
import '../shared/page-update-event';
|
||||||
import '../shared/activestorage/ujs';
|
import '../shared/activestorage/ujs';
|
||||||
import '../shared/remote-poller';
|
import '../shared/remote-poller';
|
||||||
import '../shared/rails-ujs-fix';
|
|
||||||
import '../shared/safari-11-file-xhr-workaround';
|
import '../shared/safari-11-file-xhr-workaround';
|
||||||
import '../shared/remote-input';
|
import '../shared/remote-input';
|
||||||
import '../shared/franceconnect';
|
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 Rails from '@rails/ujs';
|
||||||
import $ from 'jquery';
|
|
||||||
import debounce from 'debounce';
|
import debounce from 'debounce';
|
||||||
|
|
||||||
export { debounce };
|
export { debounce };
|
||||||
export const { fire } = Rails;
|
export const { fire, csrfToken } = Rails;
|
||||||
|
|
||||||
export function show(el) {
|
export function show(el) {
|
||||||
el && el.classList.remove('hidden');
|
el && el.classList.remove('hidden');
|
||||||
|
@ -67,17 +66,20 @@ export function ajax(options) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getJSON(url, data, method = 'get') {
|
export function getJSON(url, data, method = 'GET') {
|
||||||
data = method !== 'get' && data ? JSON.stringify(data) : data;
|
const { query, ...options } = fetchOptions(data, method);
|
||||||
return Promise.resolve(
|
|
||||||
$.ajax({
|
return fetch(`${url}${query}`, options).then((response) => {
|
||||||
method,
|
if (response.ok) {
|
||||||
url,
|
if (response.status === 204) {
|
||||||
data,
|
return null;
|
||||||
contentType: 'application/json',
|
}
|
||||||
dataType: 'json'
|
return response.json();
|
||||||
})
|
}
|
||||||
);
|
const error = new Error(response.statusText || response.status);
|
||||||
|
error.response = response;
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scrollTo(container, scrollTo) {
|
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) {
|
export function isNumeric(n) {
|
||||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||||
}
|
}
|
||||||
|
@ -120,3 +118,50 @@ export function timeoutable(promise, timeoutDelay) {
|
||||||
});
|
});
|
||||||
return Promise.race([promise, timeoutPromise]);
|
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