Skip to content

Instantly share code, notes, and snippets.

@Raynos

Raynos/stat.js Secret

Created March 31, 2013 07:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Raynos/7b1ffc4cce99a68715e5 to your computer and use it in GitHub Desktop.
Save Raynos/7b1ffc4cce99a68715e5 to your computer and use it in GitHub Desktop.
var fs = require("fs")
var paths = [
"file1.txt",
"file2.txt",
"file3.txt"
]
// let's create a state that returns a Future. i.e. callback we
// can give a callback to later
function stat(uri) {
return function future(cb) {
fs.stat(uri, cb)
}
}
// Ok cool we have files
var files = paths.map(stat)
// Ok cool we can read the first file
files[0](function (err, value) {
})
// But how do we read the first file && all the other files?
// If we call `files[0]` twice it will do two IO calls!
// Maybe with caching?
function cache(source) {
var err, value, listeners
return function future(callback) {
if (err || value) {
return callback(err, value)
}
if (listeners) {
return listeners.push(callback)
}
listeners = [callback]
source(function (_err, _value) {
err = _err
value = _value
listeners.forEach(function (f) { f(err, value) })
})
}
}
// Now whenever we read `files[0]` we will always get the same
// value! and only do one IO call
files[0] = cache(files[0])
// How do we do [Future<a>] -> Future<[a]>
// That's simple!
function list(futures) {
return function future(callback) {
var count = futures.length
var list = []
var dead
futures.forEach(function (future, index) {
future(function (err, value) {
// We need to ensure the callback only gets
// called once with one error. The rest of the
// errors are sadly ignored. This is a pain.
if (err && !dead) {
dead = true
return callback(err)
}
list[index] = value
send()
})
})
function send() {
count--
// all done
if (count === 0) {
callback(null, list)
}
}
}
}
list(files)(function (err, files) {
// Sweet!
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment