Skip to content
Browse files

Merge pull request #1 from gordonbrander/docs-and-comments

Docs and literate comments
  • Loading branch information...
2 parents b0c9f6b + 607b2a7 commit a8452b5580106cbda28e130f126204557ad4277d @Gozala committed Aug 27, 2012
Showing with 87 additions and 3 deletions.
  1. +54 −1 Readme.md
  2. +33 −2 eventual.js
View
55 Readme.md
@@ -2,8 +2,61 @@
[![Build Status](https://secure.travis-ci.org/Gozala/eventual.png)](http://travis-ci.org/Gozala/eventual)
-Abstraction for eventual values
+An abstraction for eventual values.
+
+## What is an eventual value?
+
+An eventual value is a placeholder for values that will be
+recieved asyncronously *at some point in the future*. Eventual values are typically
+used in place of callbacks for asyncronous operations. They allow you to
+return a deferred value *syncronously* that will be resolved
+*asyncronously*. Using deferred values allows you describe
+asyncronous actions in a syncronous fashion.
+
+You may have seen eventual value abstractions before: `jQuery.deferred` and
+`Promise` are both abstractions layers for eventual values.
+
+By allowing you to return a future value immediately, eventuals give you
+a handy way to avoid nested callback hell. They also make it easy to
+describe asyncronous control flows that are difficult to handle with
+callbacks ("do this when x and y are ready, then wait for any of a, b
+and c, and do that").
## Install
npm install eventual
+
+## Show me how...
+
+Let's create an eventual version of Node's `readFile`.
+
+ // Require our library files...
+ var eventuals = require('eventual'),
+ defer = eventuals.defer,
+ deliver = eventuals.deliver,
+ when = eventuals.when;
+
+ var fs = require('fs');
+
+ // Create our readFile function.
+ function readFile(file, encoding) {
+ // Create a deferred value.
+ var deferredFileContents = defer();
+
+ fs.readFile(file, (encoding || 'utf8'), function (err, contents) {
+ // When file is read, deliver the contents. If there is an
+ // error, deliver that instead.
+ deliver(deferredFileContents, (err || contents));
+ }
+ return deferredFileContents;
+ }
+
+ var deferredFoo = readFile('foo.txt');
+
+ when(deferredFoo, myCallback, myErrback);
+
+ var deferredBar = readFile('bar.txt');
+
+ var deferredBoth = group(deferredFoo, deferredBar);
+ when(deferredBoth, myOtherCallback, myOtherErrback);
+
View
35 eventual.js
@@ -46,6 +46,17 @@ var await = Method(function(value, callback) {
})
exports.await = await
+// Wait for the given value to be fulfilled, then execute a callback.
+//
+// If the value is an error object (instanceof Error), call the `onError`
+// callback (if provided). If it is any other value, call the
+// `onFulfill` callback.
+//
+// If the value passed is not an `Eventual`, `when` will execute the
+// appropriate callback immediately.
+//
+// Returns an Eventual value fulfilled with `onFulfill(fullfilmentValue)`
+// (where fullfilmentValue is what value is fulfilled with).
function when(value, onFulfill, onError) {
var deferred = defer()
onFulfill = onFulfill ? attempt(onFulfill) : identity
@@ -72,25 +83,42 @@ var pending = Name()
// Returns value if it's realized.
var valueOf = Name()
-// Type representing eventual values.
+// Define a constructor for type representing eventual values.
function Eventual() {
// Set initial values.
this[observers] = []
this[pending] = true
this[valueOf] = null
}
+
+// Implement `await` method for `Eventual` objects.
+//
+// Waits for the deferred value to be delivered, then invokes the
+// given function with the delivered value.
await.define(Eventual, function(value, callback) {
+ // If value has not yet been delivered, watch for delivery.
if (isPending(value))
watch(value, callback)
+ // Otherwise, invoke callback immediately.
else
callback(value[valueOf])
})
+
+// Implement `watchers` method for objects created with `Eventual` constructor.
+// Returns the array of observing functions.
watchers.define(Eventual, function(value) {
return value[observers]
})
+
+// Implement `isPending` method for `Eventual` objects.
+// Check if an eventual value is pending resolution.
+// Returns a boolean.
isPending.define(Eventual, function(value) {
return value[pending]
})
+
+// Implement `deliver` method for objects created with `Eventual` constructor.
+// Returns the value you pass as the resolution value.
deliver.define(Eventual, function(value, result) {
// TODO: Attempt to deliver as side effect of
// dispatch will change a value
@@ -106,7 +134,10 @@ deliver.define(Eventual, function(value, result) {
})
exports.Eventual = Eventual
-
+// Define a factory function for `Eventual`.
+// Allows you to treat Eventual construction as just another function.
+// Keeps you from having to type `new`.
+// Returns a new `Eventual` object.
function defer() {
return new Eventual()
}

0 comments on commit a8452b5

Please sign in to comment.
Something went wrong with that request. Please try again.