No JS Framework Deferred XHR/AJAX

This snippet of could should simulate a deferred so you can use this with frameworks like Knockout and not have to use jQuery.

by David Carver

JavaScript

(function(app) {
	"use strict";

	var _prototype,

		// completes the callback for a successful ajax request
		_resolve = function(_this) {
			try {
				_this._response = JSON.parse(this.response);
			} catch(e) {
				throw new Error("Invalid JSON response.");
			}

			if(_this._done) {
				_this._done.call(_this._xhr, _this._response, _this._statustext);
			}
		},

		// completes the callback for a failed ajax request
		_reject = function(_this) {
			if(_this._error) {
				_this._error.call(_this._xhr, this.statusText, this.status);
			}
		},

		// maintains common used code for XHR requests
		_xhrCommon = function(method, url, _this, data) {
			var xhr = new XMLHttpRequest();

			xhr.open(method, url, true);

			xhr.setRequestHeader("Accept", "application/json");
			xhr.setRequestHeader("Content-Type", "application/json");

			xhr.onload = function() {
				if(this.status >= 400) {
					_reject.call(this, _this);
				} else {
					_resolve.call(this, _this);
				}
			};

			xhr.onerror = function() {
				_reject.call(this, _this);
			};

			xhr.send(data || null);

			return xhr;
		},
		_getString = function(getData) {
			var getString = [];

			Object.keys(getData).forEach(function(key) {
				getString.push([
					typeof getData[key] === "object" ?
						_getString(getData[key]) :
						encodeURIComponent(getData[key]) + "=" + encodeURIComponent(getData[key])
				]);
			});

			return getString.join("&");
		};

	// provides the public available function for getting json
	app.getJSON = function(url, getData) {
		var getString = "?";

		if( !(this instanceof app.getJSON) ) {
			return new app.getJSON(url);
		}

		try {
			if(getData) {
				getString += _getString(getData);
			}
		} catch (e) {
			throw new Error("The getData object is invalid.");
		}

		url += getString;

		this._done = null;
		this._error = null;
		this._response = null;
		this._xhr = _xhrCommon("GET", url, this);
	};

	// provides the public available function for patching json
	app.patchJSON =...