Converting JSON Blob

Here’s a more flexible way to do calls in the future, sticking to fairly vanilla code. It’s made to work similar to the “request” Node.js module.

var clientID = 'Client ID here';

// Base for making requests
function request(opts, callback) {
	var req = new XMLHttpRequest();
	var url = opts.url;
	// Prepended URL part
	if('baseUrl' in opts && opts.baseUrl) {
		url = opts.baseUrl + url;
	}
	var qs = (opts.qs || {});
	var qsKeys = Object.keys(qs);
	// Add query string
	if(qsKeys.length) {
		var querystring = qsKeys
			.map(function(key) {
				return [ key, qs[key] ]
					.map(function(n) { return encodeURIComponent(n); })
					.join('=');
			})
			.join('&');
		url += '?' + querystring;
	}
	var method = opts.method || 'get';
	req.open(method, url, true);
	var headers = opts.headers || {};
	var headersKeys = Object.keys(headers);
	// Add headers
	if(headersKeys.length) {
		headersKeys.forEach(function(key) {
			req.setRequestHeader(key, headers[key]);
		});
	}
	if(callback) {
		req.addEventListener('load', function() {
				let data = this.responseText;
				// Try to parse the JSON if asked for
				if(opts.json) {
					try {
						data = JSON.parse(this.responseText);
					} catch(err) {
						callback(err, this);
						return;
					}
				}
				callback(null, data);
			});
		req.addEventListener('error', function(err) {
				callback(err, this); // Not quite sure how XMLHTTPRequest errors work
			});
	}
	req.send();
	return req;
}

function kraken(opts, callback) {
	// Assign default Twitch Kraken API base
	if('baseUrl' in opts === false) {
		opts.baseUrl = 'https://api.twitch.tv/kraken/';
	}
	// Assign default headers
	opts.headers = Object.assign({
			Accept: 'application/vnd.twitchtv.v5+json',
			'Client-ID': clientID,
		}, opts.headers || {});
	// Use JSON
	opts.json = true;
	return request(opts, callback);
}


So how can you use this? Create specific-use functions to make calls simple and clear in the rest of the code.

Key     | Type    | Description
--------+---------+--------------------------------------------------------
url     | string  | The URL, or partial URL to request
--------+---------+--------------------------------------------------------
baseUrl | string  | A part of the URL to be prepended to url
--------+---------+--------------------------------------------------------
qs      | object  | A key/value representation of the request's querystring
--------+---------+--------------------------------------------------------
headers | object  | A key/value representation of the request's headers
--------+---------+--------------------------------------------------------
json    | boolean | Whether or not to attempt to parse as JSON
--------+---------+--------------------------------------------------------

Use kraken like a default-option base function and pass just the new parts.

// Get the user object
function usernameToUserObject(username, callback) {
	return kraken({
		url: 'users',
		qs: { login: username }
	}, function(err, data) {
		if(err) {
			callback(err, data);
		}
		else if(data.users.length > 0) {
			callback(err, data.users[0]);
		}
		else {
			callback(err, null);
		}
	});
}

// Get just the "_id" key
function usernameToID(username, callback) {
	return usernameToUserObject(username, function(err, data) {
		if(err) {
			callback(err, data);
		}
		else if(data !== null) {
			callback(err, data._id);
		}
	});
}

In action:

// Will print "7676884" to the console
var req = usernameToID('alca', function(err, data) {
	if(err !== null) {
		console.log(err);
		return;
	}
	
	console.log(data);
});