Skip to content

Instantly share code, notes, and snippets.

@ithinkihaveacat
Last active January 2, 2016 04:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ithinkihaveacat/8250002 to your computer and use it in GitHub Desktop.
Save ithinkihaveacat/8250002 to your computer and use it in GitHub Desktop.

Comparison of two different approaches to structuring code that uses Promises.

Version using .then(), from Complex task dependencies:

files.getLastTwoVersions(filename)
    .then(function(items) {
        return [versions.get(items.last), 
                versions.get(items.previous)];
    })
    .spread(function(v1, v2) { 
        return diffService.compare(v1.blob, v2.blob)
    })
    .then(function(diff) {
        // voila, diff is ready. Do something with it.
    });

With wrapped functions (see below for the full source):

items = files.getLastTwoVersions(Promise.resolve(filename));
v1 = versions.get(items.get("last"));
v2 = versions.get(items.get("previous"));
diff = diffService.compare(v1.get("blob"), v2.get("blob"));
diff.then(function (s) {
    // voila, diff is ready. Do something with it
});

Note that the only real difference between the wrapped functions and the imperative version is that in the wrapped functions version, you can't access properties "directly"--you need to use the .get() method.

The function wrapping is accomplished by:

files.getLastTwoVersions = P(files.getLastTwoVersions);

(See below for P().)

// Chrome 32+
var files = {
getLastTwoVersions: function (filename) {
return {
last: "v1",
previous: "v2"
};
}
};
var versions = {
get: function (hash) {
return {
blob: "Hello World #" + hash
};
}
};
var diffService = {
compare: function (text1, text2) {
return "diff(" + text1 + ", " + text2 + ")";
}
};
filename = "myfile.txt";
// VERSION 1 (IMPERATIVE, NO PROMISES)
items = files.getLastTwoVersions(filename);
v1 = versions.get(items.last);
v2 = versions.get(items.previous);
diff = diffService.compare(v1.blob, v2.blob);
console.log("Without promises: " + diff);
// VERSION 2 (WRAPPED FUNCTIONS, PROMISES)
files.getLastTwoVersions = P(files.getLastTwoVersions);
versions.get = P(versions.get);
diffService.compare = P(diffService.compare);
items = files.getLastTwoVersions(Promise.resolve(filename));
v1 = versions.get(items.get("last"));
v2 = versions.get(items.get("previous"));
diff = diffService.compare(v1.get("blob"), v2.get("blob"));
diff.then(function (s) {
console.log("With promises: " + s);
});
function P(fn, self) {
return function () {
var args = Array.prototype.slice.call(arguments, 0);
var promise = new Promise(function (resolve, reject) {
if (self) {
args.unshift(self);
}
Promise.all(args).then(function () {
var obj;
try {
if (self) {
obj = fn.apply(arguments[0].shift(), arguments[0]);
} else {
obj = fn.apply(null, arguments[0]);
}
} catch (e) {
reject(e);
}
if (obj instanceof Promise) {
obj.then(resolve, reject);
} else {
resolve(obj);
}
}, reject);
});
// Hack to access to top level properties
if (!self) {
promise.get = P(function (p) {
return (this instanceof Object) ? this[p] : null;
}, promise);
}
return promise;
};
}
void 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment