Created
December 27, 2017 03:16
-
-
Save Yuffster/e9f0bab84664741a9f184a3ece041ce3 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
class Magic { | |
constructor(fn, a) { | |
this.__chain = [[fn, a]]; | |
} | |
get(t, a) { | |
if (a == "✨✨MAGIC✨✨") return true; | |
if (a == "resolve") { | |
return () => Magic.chain(this.__chain); | |
} | |
return (...b) => { | |
this.__chain.push([a, b]); | |
return this.__proxy; | |
} | |
} | |
} | |
Magic.chain = function MagicChain(chain, p) { | |
if (p !== undefined) { | |
if (p instanceof Promise) { | |
// Follow promises until the chain resolves to a value. | |
return p.then((v) => Magic.chain(chain, v)); | |
} else { | |
// Call the next chained method as a function on that value. | |
if (chain.length == 0) return p; | |
if (p[chain[0][0]] === undefined) { | |
throw JSON.stringify(p)+" has no function "+chain[0][0]; | |
} | |
chain[0][0] = p[chain[0][0]].bind(p); | |
return Magic.chain(chain); | |
} | |
} | |
// Work on the next call in the chain. | |
var next = chain.shift(); | |
return new Promise((resolve, reject) => { | |
var args = next[1]; | |
var pending = 0; | |
function start() { | |
var result; | |
result = Magic.chain(chain, next[0].apply(next[0], next[1])); | |
resolve(result); | |
} | |
function addArg(i, v) { | |
args[i] = v; | |
pending--; | |
if (pending==0) start(); | |
} | |
for (let i in args) { | |
let a = args[i]; | |
// Convert from magic to promise | |
if (a["✨✨MAGIC✨✨"] == true) a = a.resolve(); | |
if (a instanceof Promise) { | |
pending++; | |
a.then((v) => addArg(i, v)).catch(reject); | |
} | |
} | |
if (pending==0) start(); | |
}); | |
} | |
/* The magic function wraps everything! */ | |
function magic(fn) { | |
return (...a) => { | |
var h = new Magic(fn, a); | |
var p = new Proxy({}, h); | |
h.__proxy = p; | |
return p; | |
} | |
} | |
order = () => new Promise((resolve) => { | |
// This is an XHR request in the full codebase. | |
resolve([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); | |
}); | |
// Let's try it out. | |
longProcess = magic(order); | |
add0x = magic((v) => '0x'+v); | |
grumble = magic((v) => { | |
throw('grumble caught: '+v); | |
}); | |
pgrumble = magic((v) => { | |
return new Promise((resolve, reject) => { | |
reject("Promise rejection: "+v); | |
}); | |
}) | |
// Run it pseudosynchronously. | |
longProcess() // Does an XHR request for an array | |
.reduce((acc, cur) => acc + cur) // Returns an integer | |
.toString(16) // Returns a string | |
.toUpperCase() | |
.resolve() | |
.then((n) => console.log('final answer:', n)) | |
.catch((e) => console.error('caught', e)); | |
// Handle throws. | |
grumble("sync throw") | |
.resolve() | |
.then(console.log) | |
.catch(console.error); | |
// Handle promise rejections. | |
pgrumble("promise rejection") | |
.resolve() | |
.then(console.log) | |
.catch(console.error); | |
// Handle rejections in arguments. | |
longProcess(pgrumble('ohnoes')) | |
.resolve() | |
.then(console.log) | |
.catch(console.error); | |
longProcess(grumble('wat')) | |
.resolve() | |
.then(console.log) | |
.catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment