Skip to content

Instantly share code, notes, and snippets.

@mosson
Created February 1, 2016 11:30
Show Gist options
  • Save mosson/04b6d8ead8a2fad388ff to your computer and use it in GitHub Desktop.
Save mosson/04b6d8ead8a2fad388ff to your computer and use it in GitHub Desktop.
'use strict';
import request from 'superagent';
import _ from 'lodash';
import URL from 'url';
import Promise from 'bluebird';
const global = Function("return this")();
const methods = {
GET : 'get',
POST : 'post',
PUT : 'put',
PATCH : 'patch',
DELETE : 'del',
OPTIONS: 'options'
};
function noop() {
}
class RequestWithCache {
constructor(method, url) {
this.method = method;
this.url = url;
if (!this.constructor._cache) this.constructor._cache = {};
}
query(data) {
this.query = data;
return this;
}
send(data) {
this.data = data;
return this;
}
end(fn) {
return new Promise((fulfill, reject) => {
fn = fn || noop;
let cacheKey = this.resolveEndpoint('GET');
let cache = this.constructor._cache[cacheKey];
if (this.method === 'GET' && cache && new Date() - cache[0] < 1000 * 60) {
fulfill(fn(null, this.constructor._cache[cacheKey][1]));
} else {
if (this.method === 'POST') cacheKey = null;
if (cacheKey && this.constructor._cache[cacheKey]) {
delete this.constructor._cache[cacheKey];
}
this._end(fn, cacheKey, fulfill);
}
});
}
_end(fn, cacheKey, fulfill) {
fn = fn || noop;
let req = request[methods[this.method]](this.url);
if (this.query) req = req.query(this.query);
if (this.data) req = req.send(this.data);
req.end((err, res) => {
if (!err && cacheKey)
this.constructor._cache[cacheKey] = [new Date(), res];
fulfill(fn(err, res));
});
}
resolveEndpoint(method) {
let url = URL.parse(this.url);
if (this.query) url.query = this.query;
return `${method}_${url.format()}`;
}
get endpoint() {
let url = URL.parse(this.url);
if (this.query) url.query = this.query;
return `${this.method}_${url.format()}`;
}
}
class RequestXDomain {
constructor(method, url) {
this.method = method;
this.url = url;
this.constructor._cache = {};
}
query(data) {
this.query = data;
return this;
}
send(data) {
this.data = data;
return this;
}
end(fn) {
fn = fn || noop;
let cache = this.constructor._cache[this.endpoint];
if (this.method === 'GET' && cache && new Date() - cache[0] < 1000 * 60) {
fn(null, this.constructor._cache[this.endpoint][1]);
} else {
this._end(fn);
}
return this;
}
_end(fn) {
fn = fn || noop;
let xdr = new XDomainRequest();
xdr.open(this.method, this.url, true);
xdr.onerror = function () {
fn(xdr.responseText, null);
};
xdr.onload = function () {
fn(null, {text: xdr.responseText});
};
xdr.withCredentials = true; // to support sending cookies with CORS
setTimeout(() => {
if (this.data) {
xdr.send(this.data);
} else {
xdr.send();
}
}, 1000);
}
get endpoint() {
let url = URL.parse(this.url);
if (this.query) url.query = this.query;
return `${this.method}_${url.format()}`;
}
}
_.each(methods, (method, key) => {
if (_.isEmpty(method)) return;
RequestWithCache[method] = function (url) {
return new RequestWithCache(key, url);
};
RequestXDomain[method] = function (url) {
return new RequestXDomain(key, url);
};
});
function Request() {
if (typeof process !== "undefined" && typeof require !== "undefined") {
return RequestWithCache;
} else {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
return RequestWithCache;
} else if (typeof global.XDomainRequest !== "undefined") {
return RequestXDomain;
}
}
}
export default Request;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment