mirror of
https://github.com/freeCodeCamp/devdocs
synced 2024-11-16 19:48:10 +01:00
166 lines
3.4 KiB
JavaScript
166 lines
3.4 KiB
JavaScript
const MIME_TYPES = {
|
|
json: "application/json",
|
|
html: "text/html",
|
|
};
|
|
|
|
function ajax(options) {
|
|
applyDefaults(options);
|
|
serializeData(options);
|
|
|
|
const xhr = new XMLHttpRequest();
|
|
xhr.open(options.type, options.url, options.async);
|
|
|
|
applyCallbacks(xhr, options);
|
|
applyHeaders(xhr, options);
|
|
|
|
xhr.send(options.data);
|
|
|
|
if (options.async) {
|
|
return { abort: abort.bind(undefined, xhr) };
|
|
} else {
|
|
return parseResponse(xhr, options);
|
|
}
|
|
|
|
function applyDefaults(options) {
|
|
for (var key in ajax.defaults) {
|
|
if (options[key] == null) {
|
|
options[key] = ajax.defaults[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
function serializeData(options) {
|
|
if (!options.data) {
|
|
return;
|
|
}
|
|
|
|
if (options.type === "GET") {
|
|
options.url += "?" + serializeParams(options.data);
|
|
options.data = null;
|
|
} else {
|
|
options.data = serializeParams(options.data);
|
|
}
|
|
}
|
|
|
|
function serializeParams(params) {
|
|
return Object.entries(params)
|
|
.map(
|
|
([key, value]) =>
|
|
`${encodeURIComponent(key)}=${encodeURIComponent(value)}`,
|
|
)
|
|
.join("&");
|
|
}
|
|
|
|
function applyCallbacks(xhr, options) {
|
|
if (!options.async) {
|
|
return;
|
|
}
|
|
|
|
xhr.timer = setTimeout(
|
|
onTimeout.bind(undefined, xhr, options),
|
|
options.timeout * 1000,
|
|
);
|
|
if (options.progress) {
|
|
xhr.onprogress = options.progress;
|
|
}
|
|
xhr.onreadystatechange = function () {
|
|
if (xhr.readyState === 4) {
|
|
clearTimeout(xhr.timer);
|
|
onComplete(xhr, options);
|
|
}
|
|
};
|
|
}
|
|
|
|
function applyHeaders(xhr, options) {
|
|
if (!options.headers) {
|
|
options.headers = {};
|
|
}
|
|
|
|
if (options.contentType) {
|
|
options.headers["Content-Type"] = options.contentType;
|
|
}
|
|
|
|
if (
|
|
!options.headers["Content-Type"] &&
|
|
options.data &&
|
|
options.type !== "GET"
|
|
) {
|
|
options.headers["Content-Type"] = "application/x-www-form-urlencoded";
|
|
}
|
|
|
|
if (options.dataType) {
|
|
options.headers["Accept"] =
|
|
MIME_TYPES[options.dataType] || options.dataType;
|
|
}
|
|
|
|
for (var key in options.headers) {
|
|
var value = options.headers[key];
|
|
xhr.setRequestHeader(key, value);
|
|
}
|
|
}
|
|
|
|
function onComplete(xhr, options) {
|
|
if (200 <= xhr.status && xhr.status < 300) {
|
|
let response;
|
|
if ((response = parseResponse(xhr, options)) != null) {
|
|
onSuccess(response, xhr, options);
|
|
} else {
|
|
onError("invalid", xhr, options);
|
|
}
|
|
} else {
|
|
onError("error", xhr, options);
|
|
}
|
|
}
|
|
|
|
function onSuccess(response, xhr, options) {
|
|
if (options.success != null) {
|
|
options.success.call(options.context, response, xhr, options);
|
|
}
|
|
}
|
|
|
|
function onError(type, xhr, options) {
|
|
if (options.error != null) {
|
|
options.error.call(options.context, type, xhr, options);
|
|
}
|
|
}
|
|
|
|
function onTimeout(xhr, options) {
|
|
xhr.abort();
|
|
onError("timeout", xhr, options);
|
|
}
|
|
|
|
function abort(xhr) {
|
|
clearTimeout(xhr.timer);
|
|
xhr.onreadystatechange = null;
|
|
xhr.abort();
|
|
}
|
|
|
|
function parseResponse(xhr, options) {
|
|
if (options.dataType === "json") {
|
|
return parseJSON(xhr.responseText);
|
|
} else {
|
|
return xhr.responseText;
|
|
}
|
|
}
|
|
|
|
function parseJSON(json) {
|
|
try {
|
|
return JSON.parse(json);
|
|
} catch (error) {}
|
|
}
|
|
}
|
|
|
|
ajax.defaults = {
|
|
async: true,
|
|
dataType: "json",
|
|
timeout: 30,
|
|
type: "GET",
|
|
// contentType
|
|
// context
|
|
// data
|
|
// error
|
|
// headers
|
|
// progress
|
|
// success
|
|
// url
|
|
};
|