Skip to content

Instantly share code, notes, and snippets.

@bangedorrunt
Last active October 4, 2015 05:12
Show Gist options
  • Save bangedorrunt/77364a14911575be8a25 to your computer and use it in GitHub Desktop.
Save bangedorrunt/77364a14911575be8a25 to your computer and use it in GitHub Desktop.
JavaScript Cookbook
// Copy from `You Don't Know JS: Async & Performance` book
// by Kyle Simpson
function asyncify(fn) {
var orig_fn = fn,
intv = setTimeout(function() {
intv = null;
if (fn) fn();
}, 0);
fn = null;
return function() {
// Firing too quickly, before `intv` timer has fired to
// indicate async turn has passed?
if (intv) {
fn = orig_fn.bind.apply(
orig_fn,
// Add the wrapper's `this` to the `bind(..)`
// call parameters, as well as currying any
// passed in parameters
[this].concat([].slice.call(arguments))
);
}
// Already async
else {
// invoke original function
orig_fn.apply(this, arguments);
}
};
}
// Copyright 2014 Simon Lydell
// X11 (“MIT”) licensed. (see license.)
// Module:
function asyncify(syncFn) {
return function() {
var args = Array.prototype.slice.call(arguments)
var callback = args.pop()
setImmediate(function() {
try {
callback(null, syncFn.apply(this, args))
} catch (error) {
callback(error)
}
})
}
}
module.exports = asyncify
// Usage:
var asyncify = require("simple-asyncify")
function addSync(a, b) {
if (typeof a !== "number" || typeof b !== "number") {
throw new TypeError("add requires two numbers")
}
return a + b
}
var add = asyncify(addSync)
add(1, 2, function(error, sum) {
console.log("The sum is: " + sum)
})
add(1, function(error, sum) {
console.log(error.message)
})
console.log("Let’s do some math!")
// Let’s do some math!
// The sum is: 3
// add requires two numbers
function curry(func) {
var initial_args = [].slice.apply(arguments, [1]);
var func_args_length = func.length;
function curried(args) {
if (args.length >= func_args_length) {
return func.apply(null, args);
}
return function() {
return curried(args.concat([].slice.apply(arguments)));
};
}
return curried(initial_args);
}
// Source: http://tech.pro/blog/2097/clever-way-to-demethodize-native-js-methods
var demethodize = function(fn){
return function(){
var args = [].slice.call(arguments, 1);
return fn.apply(arguments[0], args);
};
};
// Equal to
var demethodize = Function.prototype.bind.bind(Function.prototype.call);
// Usages:
var test = "abc,def,g";
test.split(",");
//=> ["abc","def","g"]
var split = demethodize(String.prototype.split);
split(test,",");
//=> ["abc","def","g"]
// Basic syntax
function *foo(x) {
var y = x * (yield "Hello"); // Yield a value!
return y;
}
var it = foo( 6 );
var res = it.next(); // First `next`, don't pass anything
res.value; // => "Hello"
res = it.next( 7 ); // Pass `7` to waiting `yield`
res.value; // => 42
// for..of iterator
function *foo() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
return 6; // `Returned value` is ignored in generator function
}
for (var v of foo()) {
console.log( v );
}
// 1 2 3 4 5
console.log( v ); // Still `5`, not `6`
function* letters() {
console.log('a');
yield 'a';
console.log('b');
yield 'b';
while (true) {
console.log('c');
yield 'c';
}
}
var a = letters();
a.next();
a.next();
a.next();
a.next();
// Equivalent to
function letters() {
var state = 0;
return {
next: function() {
switch (state) {
case 0:
console.log('a');
state = 1;
return {
value: 'a', // Return the first yielded value.
done: false
};
case 1:
console.log('b');
state = 2;
return {
value: 'b', // Return the second yielded value.
done: false
};
case 2:
console.log('c');
return {
value: 'c', // Return the third yielded value... forever.
done: false
};
}
}
};
}
var a = letters();
a.next();
a.next();
a.next();
a.next();
function add(x, y, z) {
return x + y + z;
}
// `apply` call `bind` function with its arguments
// This kind of implementation is useful when you want
// `bind` takes its arguments as an array, as same as
// `apply` function
var args = [1, 2];
var addCurryFn = add.bind.apply(add, [this].concat(args)); // [this, 1, 2] is `add.bind` parameters
console.log(addCurryFn(3)); // => 6
// Equals to
var addCurryFn = add.bind(this, 1, 2);
console.log(addCurryFn(3)); // => 6
var MyModules = (function Manager() {
var modules = {};
function define(name, deps, impl) {
for (var i = 0; i < deps.length; i++) {
deps[i] = modules[deps[i]];
}
// Many people will have misunderstanding with invoking function
// modules[name] = impl(deps) <~~ This will NOT WORK!
// Because impl is expected to receive deps as an array of
// parameters, but impl(deps) only pass [deps[0]] value.
// Hence, the following implementation is correct
modules[name] = impl.apply(impl, deps);
}
function get(name) {
return modules[name];
}
return {
define: define,
get: get
};
})();
// Demo
MyModules.define("bar", [], function() {
function hello(who) {
return "Let me introduce: " + who;
}
return {
hello: hello
};
});
MyModules.define("foo", ["bar"], function(bar) {
var hungry = "hippo";
function awesome() {
console.log(bar.hello(hungry).toUpperCase());
}
return {
awesome: awesome
};
});
var bar = MyModules.get("bar");
var foo = MyModules.get("foo");
console.log(
bar.hello("hippo")
); // Let me introduce: hippo
foo.awesome(); // LET ME INTRODUCE: HIPPO
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment