UNPKG

@ch1/xhr

Version:
207 lines (203 loc) 6.42 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); const json = 'application/json'; const DEFAULT_TIMEOUT = 190000; const POLL_INTERVAL = 25; function Xhr(newXMLHTTPRequest, defaultTimeout = DEFAULT_TIMEOUT, pollInterval = POLL_INTERVAL) { return XhrConstructor(newXMLHTTPRequest, defaultTimeout, pollInterval); } function XhrConstructor(newXMLHTTPRequest, defaultTimeout, pollInterval) { let XHRReq = newXMLHTTPRequest; // ensure object constructor if (!(this instanceof XhrConstructor)) { return new XhrConstructor(newXMLHTTPRequest, defaultTimeout, pollInterval); } const that = this; /** @dict */ const defaultHttpHeaders = Object.create(null); init(); /** * @param {string} key * @param {string=} value * @returns {Object} */ function defaultHeader(key, value) { if (!key) { return defaultHttpHeaders; } if (!value) { if (defaultHttpHeaders[key]) { delete defaultHttpHeaders[key]; } } else { if (typeof value === 'string') { defaultHttpHeaders[key] = value; } else { defaultHttpHeaders[key] = value + ''; } } return defaultHttpHeaders; } /** * @param {XMLHttpRequest} xhr */ function setDefaultHttpHeaders(xhr) { Object.keys(defaultHttpHeaders).forEach(attr => xhr.setRequestHeader(attr, defaultHttpHeaders[attr])); } /** * @param {XMLHttpRequest} xhr * @param {Object} localHttpHeaders */ function setHttpHeaders(xhr, localHttpHeaders) { setDefaultHttpHeaders(xhr); Object.keys(localHttpHeaders).forEach(attr => { xhr.setRequestHeader(attr, localHttpHeaders[attr] + ''); }); } /** * @param {string} method * @param {string} url * @param {Object=} queryObj * @param {Object=} data * @param {string=} mimeType * @param {Object=} headers * @returns {Promise<string>} */ function newRequest(method, url, queryObj, data, mimeType, headers) { return new Promise((resolve, reject) => { const finalMimeType = mimeType === undefined ? json : mimeType; const parsedQuery = parseQuery(queryObj); const finalUrl = parsedQuery ? url + parsedQuery : url; const xhr = XHRReq(); let timer; if (method === 'POST' || method === 'PUT') { if (!data) { reject(new Error('xhr: newRequest: ' + method + ': requires data')); return; } } function clearTimer() { if (timer) { clearTimeout(timer); timer = 0; } } /** * @param {Error} reason */ function onerror(reason) { reject(reason); clearTimer(); } function onload() { // if the document isn't ready try again later if (+xhr.readyState !== 4) { setTimeout(onload, pollInterval); return; } // if the header has a 200, or 201 status handle it if (xhr.status === 200 || xhr.status === 201) { resolve(xhr.responseText); clearTimer(); return; } // otherwise error/unexpected onerror(new Error(`xhr: non 200 status: ${xhr.status}`)); } try { /** @type {function(...)} */ xhr.onload = onload; /** @type {function(...)} */ xhr.onerror = onerror; xhr.open(method, finalUrl, true); xhr.setRequestHeader('Content-Type', finalMimeType); if (headers && typeof headers === 'object') { setHttpHeaders(xhr, headers); } else { setDefaultHttpHeaders(xhr); } if (!data) { xhr.send(); } else { xhr.send(JSON.stringify(data)); } } catch (e) { onerror(e); return; } timer = setTimeout(() => { if (xhr.abort) { xhr.abort(); } onerror(new Error('xhr: request timed out')); }, defaultTimeout); }); } /** * initialize the object */ function init() { XHRReq = typeof newXMLHTTPRequest === 'function' ? newXMLHTTPRequest : () => new XMLHttpRequest(); that['defaultHeader'] = defaultHeader; that['newRequest'] = newRequest; } } /** * @param {string} url * @param {Object=} queryObj * @param {Object=} headers * @returns {Promise<string>} */ XhrConstructor.prototype['get'] = function get(url, queryObj, headers) { return this['newRequest']('GET', url, queryObj, undefined, undefined, headers); }; /** * @param {string} url * @param {Object=} data * @param {Object=} queryObj * @param {Object=} headers * @returns {Promise<string>} */ XhrConstructor.prototype['put'] = function put(url, data, queryObj, headers) { return this['newRequest']('PUT', url, queryObj, data, undefined, headers); }; /** * @param {string} url * @param {Object=} data * @param {Object=} queryObj * @param {Object=} headers * @returns {Promise<string>} */ XhrConstructor.prototype['post'] = function post(url, data, queryObj, headers) { return this['newRequest']('POST', url, queryObj, data, undefined, headers); }; /** * @param {Object=} query * @returns {string|boolean} */ function parseQuery(query) { if (!query) { return false; } if (typeof query !== 'object') { return false; } let rString = '?'; Object.keys(query).forEach((i, j) => { if (j !== 0) { rString += '&'; } rString += [i, '=', encodeURIComponent(query[i])].join(''); }); return rString; } exports.Xhr = Xhr; //# sourceMappingURL=index.cjs.js.map