Permalink
Browse files

replace 'futures' with custom Promise-implementation

  • Loading branch information...
1 parent 300f0b6 commit e15b154e9b403d99490655d1e1dab04739c9232a @sirlantis committed Jan 2, 2012
View
@@ -1,3 +1,4 @@
node_modules
lib
dist/*
+*.sublime*
View
@@ -2,31 +2,54 @@
## Why this fork?
-LiquidNode is a port of the Liquid template engine (originally written in Ruby) to *Node.js*. It uses Futures to support non-blocking, asynchronous variables/filters/blocks. Most code has been translated from Ruby to CoffeeScript, with a few adjustments (casing) to make it feel more *Coffee-/JavaScripty*.
+LiquidNode is a port of the Liquid template engine (originally written in Ruby) to *Node.js*. It uses Promises to support non-blocking, asynchronous variables/filters/blocks. Most code has been translated from Ruby to CoffeeScript, with a few adjustments (casing) to make it feel more *Coffee-/JavaScripty*.
## How [LiquidNode](https://github.com/sirlantis/liquid-node) differs from [Liquid](https://github.com/Shopify/liquid/)
The power of Node.js lies in its non-blocking nature. This presents a problem when using expressions like `{{ store.items | count }}` which may hide a blocking SQL-query.
-LiquidNode tries to solve that problem by using [Futures and Promises](http://en.wikipedia.org/wiki/Futures_and_promises). The programmer must return Future-objects from asynchronous functions - designers don't have to care about it.
+LiquidNode tries to solve that problem by using [Futures and Promises](http://en.wikipedia.org/wiki/Futures_and_promises). The programmer must return Promises from asynchronous functions - designers don't have to care about it.
-## Implementation of Futures
+## Implementation of Promises
-I decided to use the [**futures** package](https://github.com/coolaj86/futures) as an implementation of Futures (for now).
+I started with the [**futures** package](https://github.com/coolaj86/futures) as an implementation of Promises but it didn't chain as nicely as I had hoped for. So here is LiquidNode's custom Promise implementation:
```coffeescript
fs = require "fs"
-futures = require "futures"
+{async} = require "liquid-node"
class Server
name: ->
"Falkor"
+ # A deferred can either be resolved (no error) or rejected (error).
+ think: ->
+ async.promise (deferred) ->
+ later = -> deferred.resolve(42)
+ setTimeout(later, 1000)
+
+ # This is an example of how to wait for a Promise:
+ patientMethod: ->
+ deepThought = @think()
+
+ deepThought
+ .done (answer) -> console.log "The answer is: %s.", answer
+ .fail (e) -> console.log "Universe reset: %s.", e
+ .always (e) -> console.log "Look on the bright side of life."
+
+ # By the way: the left-hand side of async.promise returns a
+ # read-only view (Promise) to the Deferred. This means an
+ # Illuminati can't interfere with it on this side of the
+ # Promise.
+ #
+ # deepThought.resolve(23) isn't available.
+
+ # For node-ish callbacks you can use `deferred.node`. This
+ # will automatically resolve/reject based on the first argument.
accounts: ->
- future = futures.future()
- fs.readFile "/etc/passwd", "utf-8", (err, data) ->
- future.deliver err, data
- future
+ async.promise (deferred) ->
+ fs.readFile "/etc/passwd", "utf-8", deferred.node
+
```
## State of development
View
@@ -2,4 +2,4 @@ TODOs
- emulate FileSystem
- add missing filters
-- custom Promise implementation
+- tests for custom Promise implementation
View
@@ -5,7 +5,7 @@
{ "name": "Tony Heupel", "email": "tonyheupel@gmail.com" }
],
"description": "Node.js port of Tobias Lütke's Liquid template engine.",
- "version": "0.0.1",
+ "version": "0.0.2",
"homepage": "https://github.com/sirlantis/liquid-node",
"bugs": "https://github.com/sirlantis/liquid-node/issues",
"repository": {
@@ -19,12 +19,10 @@
},
"dependencies": {
"coffee-script": "git://github.com/jashkenas/coffee-script.git",
- "futures": ">=2.0",
"underscore": ">=1.2.3"
},
"devDependencies": {
"expresso": ">=0.9.0",
- "nodeunit": ">=0.6.4"
},
"scripts": {
"test": "expresso test/*.coffee",
View
@@ -35,21 +35,19 @@ Liquid.Variable = require("./liquid/variable")
Liquid.Template = require("./liquid/template")
Liquid.StandardFilters = require("./liquid/standard_filters")
Liquid.Condition = require("./liquid/condition")
-class Liquid.ElseCondition extends Liquid.Condition
- else: -> true
- evaluate: -> true
+Liquid.ElseCondition = require("./liquid/else_condition")
Liquid.Template.registerFilter(Liquid.StandardFilters)
-require("./liquid/tags/assign")
-require("./liquid/tags/capture")
-require("./liquid/tags/comment")
-require("./liquid/tags/decrement")
-require("./liquid/tags/for")
-require("./liquid/tags/if")
-require("./liquid/tags/ifchanged")
-require("./liquid/tags/increment")
-require("./liquid/tags/raw")
-require("./liquid/tags/unless")
+Liquid.Assign = require("./liquid/tags/assign")
+Liquid.Capture = require("./liquid/tags/capture")
+Liquid.Comment = require("./liquid/tags/comment")
+Liquid.Decrement = require("./liquid/tags/decrement")
+Liquid.For = require("./liquid/tags/for")
+Liquid.If = require("./liquid/tags/if")
+Liquid.Ifchanged = require("./liquid/tags/ifchanged")
+Liquid.Increment = require("./liquid/tags/increment")
+Liquid.Raw = require("./liquid/tags/raw")
+Liquid.Unless = require("./liquid/tags/unless")
module.exports = Liquid
View
@@ -30,3 +30,5 @@ module.exports = class Liquid
@PartialTemplateParser = ///#{@TagStart.source}.*?#{@TagEnd.source}|#{@VariableStart.source}.*?#{@VariableIncompleteEnd.source}///
@TemplateParser = ///(#{@PartialTemplateParser.source}|#{@AnyStartingTag.source})///
@VariableParser = ///\[[^\]]+\]|#{@VariableSegment.source}+\??///
+
+ @async = require("./liquid/async")
Oops, something went wrong.

0 comments on commit e15b154

Please sign in to comment.