Skip to content

Instantly share code, notes, and snippets.

@Yuffster
Created December 27, 2017 03:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Yuffster/e9f0bab84664741a9f184a3ece041ce3 to your computer and use it in GitHub Desktop.
Save Yuffster/e9f0bab84664741a9f184a3ece041ce3 to your computer and use it in GitHub Desktop.
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