/** * @fileOverview WXHR Request - Web Worker XHR * * @example * <pre> * var myHandler = new global.xhr(true), // enable workers * myHandler2 = new global.xhr(), // worker mode is disabled by default * data = { * method: 'GET', * url: 'test.txt', * success: function (data, isWorker) { * alert(data + (isWorker ? ' XHR called from Worker' : ' XHR called from Window')); * }, * error: function (status) { * alert(status); * } * }; * * myHandler.request(data); * myHandler2.request(data); * </pre> * * @author azproduction */ /**#nocode+*/ (function (global) { /**#nocode-*/ // Upgrade 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - var xhr = function (canUseWorkers) { this.canUseWorkers = (typeof canUseWorkers === 'undefined') ? false : !!canUseWorkers; }, // detect workers support workersSupported = typeof global.Worker !== 'undefined', // detect mode itIsWindow = typeof global.document !== 'undefined'; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - xhr.prototype = { request: function(params) { params.method = params.method.toUpperCase() || 'GET'; params.url = params.url || ''; params.postVars = params.method !== 'POST' ? (params.postVars || null) : null; params.success = params.success || function () {}; params.error = params.error || function () {}; // Upgrade 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (this.canUseWorkers && workersSupported && itIsWindow) { // use advanced wxhr var worker; // this is bad part mb createObjectURL will save in future worker = new global.Worker('wxhr.js'); // <<< bad worker.onmessage = function(e) { var data = e.data; // proxy response // @todo delete true parameter in Production! params[data.callback](data.data, true); }; // if worker throws error query fails worker.error = function(e) { params.error(0); }; // worker proxy request worker.postMessage({ method: params.method, url: params.url, postVars: params.postVars }); return; } // browser do not support workers or script is already works as Worker // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - var xhr = (this.createXhrObject())(), self = this; xhr.onreadystatechange = function() { try { if (xhr.readyState !== 4) { return; } self.processResponse(params, { status: xhr.status, responseText: xhr.responseText, contentType: xhr.getResponseHeader('Content-type') }); } catch (e) { params.error(xhr.status); } }; xhr.open(params.method, params.url, true); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.send(params.postVars); }, createXhrObject: function() { // Factory method. var methods = [ function() { return new XMLHttpRequest(); }, function() { return new ActiveXObject('Msxml2.XMLHTTP'); }, function() { return new ActiveXObject('Microsoft.XMLHTTP'); } ]; for (var i = 0, len = methods.length; i < len; i++) { try { methods[i](); } catch(e) { continue; } // If we reach this point, method[i] worked. this.createXhrObject = methods[i]; // Memoize the method. return methods[i]; } // If we reach this point, none of the methods worked. throw new Error('SimpleHandler: Could not create an XHR object.'); }, processResponse: function (params, xhr) { if (xhr.status === 200) { if (xhr.contentType.match(/^application\/json/)) { params.success(JSON.parse(xhr.responseText)); } else { params.success(xhr.responseText); } } else { params.error(xhr.status); } } }; // Upgrade 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (!itIsWindow) { // worker mode: listen for requests global.addEventListener('message', function(e) { var data = e.data; // proxy success data.success = function (data) { global.postMessage({ callback: 'success', data: data }); }; // proxy error data.error = function (status) { global.postMessage({ callback: 'error', data: status }); }; var xhrRequest = new xhr(); xhrRequest.request(data); }, false); } else { // script mode: export xhr global.xhr = xhr; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // global.xhr = xhr; /**#nocode+*/ }(this)); /**#nocode-*/
Source: https://habr.com/ru/post/110712/
All Articles