Last active
July 10, 2021 13:37
-
-
Save japboy/292de2baa84b1019bfcb to your computer and use it in GitHub Desktop.
My useful curried functions returns Promises
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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(); }) | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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