Skip to content

Instantly share code, notes, and snippets.

@jabyrd3
Last active January 26, 2016 05:46
Show Gist options
  • Select an option

  • Save jabyrd3/c8b594021e65f39e3ad4 to your computer and use it in GitHub Desktop.

Select an option

Save jabyrd3/c8b594021e65f39e3ad4 to your computer and use it in GitHub Desktop.
(function () {
'use strict';
/* globals _*/
/* - API access prettifier and standardizer
* we use this service heavily to take some of the pain out of writing api calls all the time.
* it wraps the native angular $http method. It'd be a simple task to write a non-angular specific
* version of this though.
*
* - Sample Usage:
* apiService.users(42).report(18).put({'sample': 'json'}).then(function(response){
* //do stuff with the response
* }).catch(function(){});
*/
angular.module('api', ['application.config'])
// this constant should be precompiled by a gulp/grunt task, not hardcoded as it is here.
// ie: we look through the final js for apiService.here().are().some().array().entries()
// ^ would generate teh constant as ['here', 'are', 'some', 'array', 'entries']
.constant('endpoints', ['this', 'array', 'is', 'every', 'possible', 'known', 'word', 'in', 'target', 'api'])
// this constant is the url of your apiRoot
.constant('apiUrl', 'http://yoururl.com/apiRoot')
.factory('apiService', ['$rootScope', '$http', '$q', 'apiUrl', 'endpoints',
function ($rootScope, $http, $q, apiUrl, endpoints) {
var service = this;
// worker for experimental web-worker request functionality
var requestWorker = new Worker('assets/static/fastworker.js');
// utility function to mash our URL together
service.concatenator = function (map, query) {
var concat = '';
_.each(map, function (val, key) {
if (val !== false) {
concat += '/' + key + '/' + val;
} else {
concat += '/' + key;
}
});
if (query) {
concat += query;
}
return concat;
};
// local object to store query in progress while chaining.
service.map = {};
// local object to store query body before request
service.bodyObj = {};
// utility function to clear local request state
service.reset = function () {
service.bodyObj = {};
service.map = {};
};
service.workerRequest = function (method, body) {
// clone vars to scope and reset so that we don't get collisions
var deferred = $q.defer();
var local = {
bodyObj: angular.copy(service.bodyObj),
map: angular.copy(service.map)
};
// reset the service for the next request.
service.reset();
requestWorker.postMessage([method, apiUrl, local.map, body, local.bodyObj]);
requestWorker.onmessage = function (ev) {
if (ev.data !== 401) {
// let the consumer deal with the output, this is experimental
deferred.resolve(ev.data);
} else {
if (ev.data === 401) {
console.warn('Not logged in, redirecting');
// If there's a cookie, erase it on this event
$rootScope.$broadcast('loggedout');
deferred.reject(ev);
}
}
};
return deferred.promise;
};
// genericize calls for different HTTP method assignment
service.genericHttp = function (method, queryString) {
// clone vars to scope and reset so that we don't get collisions
var local = {
bodyObj: angular.copy(service.bodyObj),
map: angular.copy(service.map)
};
// clear service for subsequent reqs
service.reset();
var deferred = $q.defer();
// actually make the http call
$http({
method: method,
url: apiUrl + service.concatenator(local.map,
queryString),
data: local.bodyObj,
$http({
method: method,
url: apiUrl + service.concatenator(local.map, queryString),
data: local.bodyObj,
headers: method !== 'GET' ? {
'Content-Type': 'application/json'
} : null
})
.then(function (response) {
deferred.resolve(response.data);
}, function (error) {
var status = error.status;
var statusText = error.statusText;
var data = error.data;
service.reset();
// useful message for our consumer
deferred.reject({
data: data,
status: status,
statusText: statusText
});
});
return deferred.promise;
};
// sample usage: apiService.gallery(12).asset(3).comment('Note','shot is underexposed').post();
// dynamically generate a function per parameter for each endpoint. this allows us to chain.
_.each(endpoints, function (endpoint) {
this[endpoint] = function (inp) {
// inp needs to be an int or a string,
// advance datatypes will just make a broken url
// there should be some validation eventually.
if (inp) {
service.map[endpoint] = inp;
} else {
service.map[endpoint] = false;
}
return this;
};
});
// bind http verbs to service
service.post = function (passObj) {
if (passObj) {
service.bodyObj = passObj;
}
return service.genericHttp('POST');
};
service.get = function (querystring) {
return service.genericHttp('GET', querystring);
};
service.delete = function () {
return service.genericHttp('DELETE');
};
service.wwGet = function (q) {
return service.workerRequest('GET', q);
};
service.put = function (passObj) {
if (passObj) {
service.bodyObj = passObj;
}
return service.genericHttp('PUT');
};
service.patch = function () {
return service.genericHttp('PATCH');
};
service.wwPost = function (o) {
if (o) {
service.bodyObj = o;
}
return service.workerRequest('POST');
};
return this;
}
]);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment