Skip to content

Instantly share code, notes, and snippets.

@japboy
Last active July 10, 2021 13:37
Show Gist options
  • Save japboy/292de2baa84b1019bfcb to your computer and use it in GitHub Desktop.
Save japboy/292de2baa84b1019bfcb to your computer and use it in GitHub Desktop.
My useful curried functions returns Promises
'use strict';
var _ = require('underscore');
var $ = require('jquery');
var global = global || window, doc = global.document, nav = global.navigator;
/**
* Function returns curried function
* @param {Function} func A function being curried
* @returns {Function} A curried function
*/
exports.curry = function (func) {
return function partial () {
var argsA = _.toArray(arguments);
if (argsA.length >= func.length) return func.apply(undefined, argsA);
return function () {
var argsB = _.toArray(arguments);
return partial.apply(undefined, argsA.concat(argsB));
};
};
};
/**
* Promise returns a value
* @returns {Object} a jQuery Deferred's Promise object
*/
exports.promisify = function (val) {
var id, dfr = new $.Deferred();
id = global.setTimeout(function () {
global.clearTimeout(id);
if (_.isError(val)) return dfr.reject(val);
dfr.resolve(val);
}, 1);
return dfr.promise();
};
/**
* Function returns curried function and immediate function as a Promise
* @param {Function} func An immediate function being curried
* @returns {Function|Object} A curried function or a jQuery Deferred's Promise object
*/
exports.immediatify = function (func) {
return function partial () {
var argsA = _.toArray(arguments);
if (argsA.length < func.length) {
return function () {
var argsB = _.toArray(arguments);
return partial.apply(undefined, argsA.concat(argsB));
};
}
var id, dfr = new $.Deferred();
var val = func.apply(undefined, argsA); // Immediate evaltuation
id = global.setTimeout(function () {
global.clearTimeout(id);
if (_.isError(val)) return dfr.reject(val);
dfr.resolve(val);
}, 1);
return dfr.promise();
};
};
/**
* Function returns curried function and lazy function as a Promise
* @param {Function} func An immediate function being curried and lazy evaluated
* @returns {Function|Object} A curried function or a jQuery Deferred's Promise object
*/
exports.lazify = function (func) {
return function partial () {
var argsA = _.toArray(arguments);
if (argsA.length < func.length) {
return function () {
var argsB = _.toArray(arguments);
return partial.apply(undefined, argsA.concat(argsB));
};
}
var id, dfr = new $.Deferred();
id = global.setTimeout(function () {
global.clearTimeout(id);
var val = func.apply(undefined, argsA); // Lazy evaluation
if (_.isError(val)) return dfr.reject(val);
dfr.resolve(val);
}, 1);
return dfr.promise();
};
};
/**
* Function returns curried function and chain pre and post processes as Promise
* @param {Object} pre A pre-process defined as a jQuery Deferred's Promise object
* @param {Function} main A main process function evaluated as a jQuery Deferred's Promise object
* @param {Function} post A post-process function evaluated as a jQuery Deferred's Promise object
* @param {Function} error An error process function evaluated as a jQuery Deferred's Promise object
* @returns {Function|Object} A curried function or a jQuery Deferred's Promise object
*/
exports.decoratify = exports.curry(function (pre, main, post, error) {
return function () {
var argsA = _.toArray(arguments);
return pre.then(function () {
var argsB = _.toArray(arguments);
return main.apply(undefined, argsA.concat(argsB));
}).then(post, error);
};
});
/**
* Promise concatenates array values as promises
* @param {Array} items Array values will be tranformed to promises
* @param {Function} promisify A function transforms `items` to promises
* @returns {Object} a jQuery Deferred's Promise object
*/
exports.promisedMap = function (items, promisify) {
var dfr = new $.Deferred(), promises = _.map(items, promisify);
$.when.apply(undefined, promises).then(dfr.resolve, dfr.reject);
return dfr.promise();
};
/**
* Promise returns timer sleep
* @param {Number} millisec Milliseconds to wait
* @returns {Object} a jQuery Deferred's Promise object
*/
exports.sleep = function (millisec) {
if (!millisec) millisec = 80;
var id, dfr = new $.Deferred();
id = global.setTimeout(function () {
global.clearTimeout(id);
dfr.resolve(millisec);
}, millisec);
return dfr.promise();
};
/**
* Promise returns DOMContentLoaded event
* @see https://api.jquery.com/ready/
* @returns {Object} a jQuery Deferred's Promise object
*/
exports.contentLoaded = function () {
var dfr = new $.Deferred();
$(doc).ready(dfr.resolve);
return dfr.promise();
};
/**
* Promise returns DOM Image element
* @param {String} uri An image URI to load
* @returns {Object} a jQuery Deferred's Promise object
*/
exports.imageLoad = function (uri) {
var dfr = new $.Deferred(), $img = $(doc.createElement('img'));
$img.one('error', function (ev) {
$(ev.target).remove();
dfr.reject(new global.Error(uri));
});
$img.one('load', function (ev) {
dfr.resolve(ev.target);
});
$img.attr('src', uri);
return dfr.promise();
};
/**
* Promise chainable curried function returns XHR as a Promise
* @param {String} method A method to request XHR process
* @param {String} uri A URI to request to
* @param {String|Object|Array} data A data will be sent
* @returns {Function|Object} A curried function or a jQuery Deferred's Promise object
*/
exports.xhr = exports.curry(function (method, uri, data) {
return $.ajax({
data: data,
method: method,
url: uri
});
});
/**
* Promise returns current position as Google Maps API LatLng instance from Geolocation API
* @see https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition
* @see https://developers.google.com/maps/documentation/javascript/reference#LatLng
* @param {Object} options A PositionOptions object of Geolocation API
* @returns {Object} a jQuery Deferred's Promise object
*/
exports.currentPosition = function (options) {
if (null == options) options = { enableHighAccuracy: true, timeout: 10000 };
var dfr = new $.Deferred();
var success = function (pos) {
var latLng = [pos.coords.latitude, pos.coords.longitude];
dfr.resolve(latLng);
};
var error = dfr.reject;
nav.geolocation.getCurrentPosition(success, error, options);
return dfr.promise();
};
/**
* A localStorage wrapper returns a Promise
*/
exports.localStore = {
set: exports.lazify(function (key, val) {
// Avoid Exception on Safari private mode
try {
return global.localStorage.setItem(key, val);
} catch (err) {
return err;
}
}),
get: exports.lazify(function (key) { return global.localStorage.getItem(key); }),
clear: exports.lazify(function () { return global.localStorage.clear(); })
};
/**
* A sessionStorage wrapper returns a Promise
*/
exports.sessionStore = {
set: exports.lazify(function (key, val) {
// Avoid Exception on Safari private mode
try {
return global.sessionStorage.setItem(key, val);
} catch (err) {
return err;
}
}),
get: exports.lazify(function (key) { return global.sessionStorage.getItem(key); }),
clear: exports.lazify(function () { return global.sessionStorage.clear(); })
};
'use strict';
import 'babel/polyfill';
import _ from 'underscore';
let w = global, d = w.document, n = w.navigator, Promise = w.Promise;
let GM = w.google.maps;
/**
* serialize an object
*/
export let serialize = (data={}) => {
return _.chain(data)
.pairs()
.map((pair) => {
if (_.isArray(pair[1])) return _.map(pair[1], (val) => `${pair[0]}[]=${val}`);
return `${pair[0]}=${pair[1]}`;
})
.flatten()
.value()
.join('&')
.replace(/%20/g, '+');
};
/**
* Function returns curried function
* @param {Function} func A function being curried
* @returns {Function} A curried function
*/
export let curry = (func) => {
let partial = (...args) => {
if (args.length >= func.length) return func.apply(undefined, args);
return (..._args) => partial.apply(undefined, args.concat(_args));
};
return partial;
};
/**
* Promise returns a value
* @returns {Object} A Promise object
*/
export let promisify = (val) => {
return new Promise((resolve, reject) => {
if (_.isError(val)) return reject(val);
resolve(val);
});
};
/**
* Function returns curried function and immediate function as a Promise
* @param {Function} func An immediate function being curried
* @returns {Function|Object} A curried function or a Promise object
*/
export let immediatify = (func) => {
let partial = (...args) => {
if (args.length < func.length) return (..._args) => partial.apply(undefined, args.concat(_args));
let val = func.apply(undefined, args); // Immediate evaltuation
return new Promise((resolve, reject) => {
if (_.isError(val)) return reject(val);
resolve(val);
});
};
return partial;
};
/**
* Function returns curried function and lazy function as a Promise
* @param {Function} func An immediate function being curried and lazy evaluated
* @returns {Function|Object} A curried function or a Promise object
*/
export let lazify = (func) => {
let partial = (...args) => {
if (args.length < func.length) return (..._args) => partial.apply(undefined, args.concat(_args));
return new Promise((resolve, reject) => {
let id = w.setTimeout(() => {
w.clearTimeout(id);
let val = func.apply(undefined, args); // Lazy evaluation
if (_.isError(val)) return reject(val);
resolve(val);
}, 1);
});
};
return partial;
};
/**
* Promise concatenates array values as Promises
* @param {Array} items Array values will be tranformed to Promises
* @param {Function} func A function transforms `items` to Promises
* @returns {Object} A Promise object
*/
export let promisedArray = (items, func) => {
return new Promise((resolve, reject) => {
let promises = _.map(items, func);
Promise.all(promises).then(resolve, reject);
});
};
/**
* Promise returns timer sleep
* @param {Number} millisec Milliseconds to wait
* @returns {Object} A Promise object
*/
export let sleep = (millisec=80) => {
return new Promise((resolve, reject) => {
let id = w.setTimeout(() => {
w.clearTimeout(id);
resolve(millisec);
}, millisec);
});
};
/**
* Promise returns DOMContentLoaded event
* @returns {Object} A Promise object
*/
export let contentLoaded = () => {
return new Promise((resolve, reject) => {
let loaded = (ev) => {
ev.target.removeEventListener(ev.type, loaded);
resolve(ev.target);
};
d.addEventListener('DOMContentLoaded', loaded, false);
});
};
/**
* Promise returns DOM Image element
* @param {String} uri An image URI to load
* @returns {Object} A Promise object
*/
export let imageLoad = (uri) => {
return new Promise((resolve, reject) => {
let img = d.createElement('img');
let error = (ev) => {
ev.target.removeEventListener(ev.type, error);
ev.target.parentNode.removeChild(ev.target);
reject(new w.Error(uri));
};
let load = (ev) => {
ev.target.removeEventListener(ev.type, load);
resolve(ev.target);
};
img.addEventListener('error', error, false);
img.addEventListener('load', load, false);
img.setAttribute('src', uri);
});
};
/**
* Promise chainable curried function returns XHR as a promise
* @param {String} method A method to request XHR process
* @param {String} uri A URI to request to
* @param {Object} data A data will be sent
* @returns {Function|Object} A curried function or a Promise object
*/
export let xhr = curry((method, uri, data={}) => {
return new Promise((resolve, reject) => {
let req = new w.XMLHttpRequest();
let readystatechange = (ev) => {
if (ev.target.DONE !== ev.target.readyState) return;
ev.removeEventListener(ev.type, readystatechange);
if (200 === ev.target.status) {
let response, ctype = ev.target.getResponseHeader('Content-Type');
switch (ctype) {
case 'application/json':
case 'text/json':
response = w.JSON.parse(ev.target.responseText);
break;
case 'application/xml':
case 'text/xml':
response = ev.target.responseXML;
break;
default:
response = ev.target.responseText;
}
resolve({ 'response': response });
} else {
reject(new w.Error(`${ev.target.status} ${ev.target.responseText}`));
}
};
req.addEventListener('readystatechange', readystatechange, false);
switch (method) {
case 'GET':
req.open(method, `${uri}?${serialize(data)}`, true);
req.send();
break;
case 'POST':
req.open(method, uri, true);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send(serialize(data));
break;
}
});
});
/**
* Promise returns current position as Google Maps API LatLng instance from Geolocation API
* @see https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition
* @see https://developers.google.com/maps/documentation/javascript/reference#LatLng
* @param {Object} options A PositionOptions object of Geolocation API
* @returns {Object} a jQuery Deferred's Promise object
*/
export let currentPosition = (options={ enableHighAccuracy: true, timeout: 10000 }) => {
return new Promise((resolve, reject) => {
let success = (pos) => {
let latLng = new GM.LatLng(pos.coords.latitude, pos.coords.longitude);
resolve(latLng);
};
let error = reject;
n.geolocation.getCurrentPosition(success, error, options);
});
};
/**
* A localStorage wrapper returns a Promise
*/
export let localStore = {
set: lazify((key, val) => {
// Avoid Exception on Safari private mode
try {
return w.localStorage.setItem(key, val);
} catch (err) {
return err;
}
}),
get: lazify((key) => w.localStorage.getItem(key)),
clear: lazify(() => w.localStorage.clear())
};
/**
* A sessionStorage wrapper returns a Promise
*/
export let sessionStore = {
set: lazify((key, val) => {
// Avoid Exception on Safari private mode
try {
return w.sessionStorage.setItem(key, val);
} catch (err) {
return err;
}
}),
get: lazify((key) => w.sessionStorage.getItem(key)),
clear: lazify(() => w.sessionStorage.clear())
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment