x-http-client
Version:
An http client to simplify sending requests (HTTP & JSONP) in the browser.
148 lines (128 loc) • 3.81 kB
JavaScript
var isFunction = require('x-common-utils/isFunction');
var HttpResponse = require('../class/HttpResponse');
var addTimeoutListener = require('./addTimeoutListener');
var fireCallbacks = require('../shared/fireCallbacks');
var noop = require('../shared/noop');
var constants = require('../shared/constants');
var ERR_ABORTED = constants.ERR_ABORTED;
var ERR_CANCELED = constants.ERR_CANCELED;
var ERR_NETWORK = constants.ERR_NETWORK;
var ERR_RESPONSE = constants.ERR_RESPONSE;
var ERR_TIMEOUT = constants.ERR_TIMEOUT;
/**
* Check whether the request is aborted.
*
* @param {XMLHttpRequest} xhr The XMLHttpRequest.
* @returns {boolean} Returns `true` if it is aborted.
*/
function isAborted(xhr) {
var status = +xhr.status;
var responseURL = xhr.responseURL;
if (typeof responseURL !== 'string') {
responseURL = '';
}
return status === 0 && responseURL.indexOf('file:') !== 0;
}
/**
* Add event listeners to the http request. This function will overwite the `cancel` method on the given `HttpReqest`
* instance.
*
* @param {HttpRequest} request The http request to add event listeners.
*/
function addEventListeners(request) {
var xhr = request.xhr;
var options = request.options;
var requestType = request.requestType;
var response = new HttpResponse(request);
var isResponseOk = options.isResponseOk;
var clearTimeoutEvent = null;
var timeout = parseInt(options.timeout, 10) || 0;
/**
* Cancel the request.
*/
var cancel = function () {
clearEvents();
if (xhr.abort) {
try {
xhr.abort();
} catch (e) {
// empty
}
}
finish(ERR_CANCELED);
};
/**
* The function to clear events.
*/
var clearEvents = function () {
// Set clearEvents to the noop function.
clearEvents = noop;
xhr.onabort = null;
xhr.onerror = null;
xhr.onreadystatechange = null;
xhr.ontimeout = null;
if (clearTimeoutEvent) {
clearTimeoutEvent();
clearTimeoutEvent = null;
}
};
/**
* The function finish the request.
*
* @param {string} code The error code on error. If no error occured, the code is `null`.
*/
var finish = function (code) {
// Set finish to the noop function.
finish = noop;
// Set cancel to the noop function.
cancel = noop;
// Mark this request as finished.
request.finished = true;
// Clear events.
clearEvents();
// Fire callbacks.
fireCallbacks(code, response);
};
xhr.onabort = function () {
finish(ERR_ABORTED);
};
xhr.onerror = function () {
finish(ERR_NETWORK);
};
xhr.onreadystatechange = function () {
if (+xhr.readyState === 4) {
if (isAborted(xhr)) {
finish(ERR_ABORTED);
} else if (isFunction(isResponseOk)) {
if (isResponseOk(requestType, response)) {
finish(null);
} else {
finish(ERR_RESPONSE);
}
} else {
finish(null);
}
}
};
/**
* Cancel the request.
*/
request.cancel = function () {
cancel();
};
// Add timeout listener
if (timeout > 0) {
clearTimeoutEvent = addTimeoutListener(xhr, timeout, function () {
clearEvents();
if (xhr.abort) {
try {
xhr.abort();
} catch (e) {
// empty
}
}
finish(ERR_TIMEOUT);
});
}
}
module.exports = addEventListeners;