tricks
Version:
ES6 modules
104 lines (82 loc) • 2.46 kB
JavaScript
// XHR: uses CORS to make requests
import instanceOf from '../../object/instanceOf.js';
import extract from '../../string/extract.js';
import jsonParse from '../../string/jsonParse.js';
import tryCatch from '../../object/tryCatch.js';
import rewire from '../../object/rewire.js';
const match_headers = /([\da-z-]+):\s*(.*);?/gi;
export default rewire(xhr);
function xhr(method, url, responseType, headers, data, callback) {
const r = new XMLHttpRequest();
// Make it CAPITAL
method = method.toUpperCase();
// Define the callback function
r.onload = () => {
// Response
let response = r.response;
// Was this text
if (!response && (r.responseType === '' || r.responseType === 'text')) {
response = r.responseText;
}
// Is this json?
if (typeof(response) === 'string' && responseType === 'json') {
// Set this to the json response
// Fallback if the browser did not defined responseJSON...
response = r.responseJSON || jsonParse(r.responseText || r.response);
}
const headers = extract(r.getAllResponseHeaders(), match_headers);
headers.statusCode = r.status;
callback(response, headers);
};
r.onerror = r.onload;
// Should we add the query to the URL?
if (method === 'GET' || method === 'DELETE') {
data = null;
}
else if (data && typeof (data) !== 'string' &&
!instanceOf(data, window.FormData) &&
!instanceOf(data, window.File) &&
!instanceOf(data, window.Blob)) {
// Loop through and add formData
data = toFormData(data);
}
// Open the path, async
r.open(method, url, true);
// Set responseType if supported
if ('responseType' in r) {
tryCatch(() => {
// Setting this to an unsupported value can result in a "SYNTAX_ERR: DOM Exception 12"
r.responseType = responseType;
});
}
else if (responseType === 'blob') {
r.overrideMimeType('text/plain; charset=x-user-defined');
}
// Set any bespoke headers
if (headers) {
for (const x in headers) {
r.setRequestHeader(x, headers[x]);
}
}
r.send(data);
return r;
}
function toFormData(data) {
const f = new FormData();
for (const x in data) {
if (Object.prototype.hasOwnProperty.call(data, x)) {
if (instanceOf(data[x], window.HTMLInputElement) && 'files' in data[x]) {
if (data[x].files.length > 0) {
f.append(x, data[x].files[0]);
}
}
else if (instanceOf(data[x], window.Blob)) {
f.append(x, data[x], data.name);
}
else {
f.append(x, data[x]);
}
}
}
return f;
}