Template Upload
This commit is contained in:
15
node_modules/slide/LICENSE
generated
vendored
Normal file
15
node_modules/slide/LICENSE
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
143
node_modules/slide/README.md
generated
vendored
Normal file
143
node_modules/slide/README.md
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
# Controlling Flow: callbacks are easy
|
||||
|
||||
## What's actually hard?
|
||||
|
||||
- Doing a bunch of things in a specific order.
|
||||
- Knowing when stuff is done.
|
||||
- Handling failures.
|
||||
- Breaking up functionality into parts (avoid nested inline callbacks)
|
||||
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Abandoning convention and consistency.
|
||||
- Putting all callbacks inline.
|
||||
- Using libraries without grokking them.
|
||||
- Trying to make async code look sync.
|
||||
|
||||
## Define Conventions
|
||||
|
||||
- Two kinds of functions: *actors* take action, *callbacks* get results.
|
||||
- Essentially the continuation pattern. Resulting code *looks* similar
|
||||
to fibers, but is *much* simpler to implement.
|
||||
- Node works this way in the lowlevel APIs already, and it's very flexible.
|
||||
|
||||
## Callbacks
|
||||
|
||||
- Simple responders
|
||||
- Must always be prepared to handle errors, that's why it's the first argument.
|
||||
- Often inline anonymous, but not always.
|
||||
- Can trap and call other callbacks with modified data, or pass errors upwards.
|
||||
|
||||
## Actors
|
||||
|
||||
- Last argument is a callback.
|
||||
- If any error occurs, and can't be handled, pass it to the callback and return.
|
||||
- Must not throw. Return value ignored.
|
||||
- return x ==> return cb(null, x)
|
||||
- throw er ==> return cb(er)
|
||||
|
||||
```javascript
|
||||
// return true if a path is either
|
||||
// a symlink or a directory.
|
||||
function isLinkOrDir (path, cb) {
|
||||
fs.lstat(path, function (er, s) {
|
||||
if (er) return cb(er)
|
||||
return cb(null, s.isDirectory() || s.isSymbolicLink())
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
# asyncMap
|
||||
|
||||
## Usecases
|
||||
|
||||
- I have a list of 10 files, and need to read all of them, and then continue when they're all done.
|
||||
- I have a dozen URLs, and need to fetch them all, and then continue when they're all done.
|
||||
- I have 4 connected users, and need to send a message to all of them, and then continue when that's done.
|
||||
- I have a list of n things, and I need to dosomething with all of them, in parallel, and get the results once they're all complete.
|
||||
|
||||
|
||||
## Solution
|
||||
|
||||
```javascript
|
||||
var asyncMap = require("slide").asyncMap
|
||||
function writeFiles (files, what, cb) {
|
||||
asyncMap(files, function (f, cb) {
|
||||
fs.writeFile(f, what, cb)
|
||||
}, cb)
|
||||
}
|
||||
writeFiles([my, file, list], "foo", cb)
|
||||
```
|
||||
|
||||
# chain
|
||||
|
||||
## Usecases
|
||||
|
||||
- I have to do a bunch of things, in order. Get db credentials out of a file,
|
||||
read the data from the db, write that data to another file.
|
||||
- If anything fails, do not continue.
|
||||
- I still have to provide an array of functions, which is a lot of boilerplate,
|
||||
and a pita if your functions take args like
|
||||
|
||||
```javascript
|
||||
function (cb) {
|
||||
blah(a, b, c, cb)
|
||||
}
|
||||
```
|
||||
|
||||
- Results are discarded, which is a bit lame.
|
||||
- No way to branch.
|
||||
|
||||
## Solution
|
||||
|
||||
- reduces boilerplate by converting an array of [fn, args] to an actor
|
||||
that takes no arguments (except cb)
|
||||
- A bit like Function#bind, but tailored for our use-case.
|
||||
- bindActor(obj, "method", a, b, c)
|
||||
- bindActor(fn, a, b, c)
|
||||
- bindActor(obj, fn, a, b, c)
|
||||
- branching, skipping over falsey arguments
|
||||
|
||||
```javascript
|
||||
chain([
|
||||
doThing && [thing, a, b, c]
|
||||
, isFoo && [doFoo, "foo"]
|
||||
, subChain && [chain, [one, two]]
|
||||
], cb)
|
||||
```
|
||||
|
||||
- tracking results: results are stored in an optional array passed as argument,
|
||||
last result is always in results[results.length - 1].
|
||||
- treat chain.first and chain.last as placeholders for the first/last
|
||||
result up until that point.
|
||||
|
||||
|
||||
## Non-trivial example
|
||||
|
||||
- Read number files in a directory
|
||||
- Add the results together
|
||||
- Ping a web service with the result
|
||||
- Write the response to a file
|
||||
- Delete the number files
|
||||
|
||||
```javascript
|
||||
var chain = require("slide").chain
|
||||
function myProgram (cb) {
|
||||
var res = [], last = chain.last, first = chain.first
|
||||
chain([
|
||||
[fs, "readdir", "the-directory"]
|
||||
, [readFiles, "the-directory", last]
|
||||
, [sum, last]
|
||||
, [ping, "POST", "example.com", 80, "/foo", last]
|
||||
, [fs, "writeFile", "result.txt", last]
|
||||
, [rmFiles, "./the-directory", first]
|
||||
], res, cb)
|
||||
}
|
||||
```
|
||||
|
||||
# Conclusion: Convention Profits
|
||||
|
||||
- Consistent API from top to bottom.
|
||||
- Sneak in at any point to inject functionality. Testable, reusable, ...
|
||||
- When ruby and python users whine, you can smile condescendingly.
|
1
node_modules/slide/index.js
generated
vendored
Normal file
1
node_modules/slide/index.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports=require("./lib/slide")
|
65
node_modules/slide/lib/async-map-ordered.js
generated
vendored
Normal file
65
node_modules/slide/lib/async-map-ordered.js
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
|
||||
throw new Error("TODO: Not yet implemented.")
|
||||
|
||||
/*
|
||||
usage:
|
||||
|
||||
Like asyncMap, but only can take a single cb, and guarantees
|
||||
the order of the results.
|
||||
*/
|
||||
|
||||
module.exports = asyncMapOrdered
|
||||
|
||||
function asyncMapOrdered (list, fn, cb_) {
|
||||
if (typeof cb_ !== "function") throw new Error(
|
||||
"No callback provided to asyncMapOrdered")
|
||||
|
||||
if (typeof fn !== "function") throw new Error(
|
||||
"No map function provided to asyncMapOrdered")
|
||||
|
||||
if (list === undefined || list === null) return cb_(null, [])
|
||||
if (!Array.isArray(list)) list = [list]
|
||||
if (!list.length) return cb_(null, [])
|
||||
|
||||
var errState = null
|
||||
, l = list.length
|
||||
, a = l
|
||||
, res = []
|
||||
, resCount = 0
|
||||
, maxArgLen = 0
|
||||
|
||||
function cb (index) { return function () {
|
||||
if (errState) return
|
||||
var er = arguments[0]
|
||||
var argLen = arguments.length
|
||||
maxArgLen = Math.max(maxArgLen, argLen)
|
||||
res[index] = argLen === 1 ? [er] : Array.apply(null, arguments)
|
||||
|
||||
// see if any new things have been added.
|
||||
if (list.length > l) {
|
||||
var newList = list.slice(l)
|
||||
a += (list.length - l)
|
||||
var oldLen = l
|
||||
l = list.length
|
||||
process.nextTick(function () {
|
||||
newList.forEach(function (ar, i) { fn(ar, cb(i + oldLen)) })
|
||||
})
|
||||
}
|
||||
|
||||
if (er || --a === 0) {
|
||||
errState = er
|
||||
cb_.apply(null, [errState].concat(flip(res, resCount, maxArgLen)))
|
||||
}
|
||||
}}
|
||||
// expect the supplied cb function to be called
|
||||
// "n" times for each thing in the array.
|
||||
list.forEach(function (ar) {
|
||||
steps.forEach(function (fn, i) { fn(ar, cb(i)) })
|
||||
})
|
||||
}
|
||||
|
||||
function flip (res, resCount, argLen) {
|
||||
var flat = []
|
||||
// res = [[er, x, y], [er, x1, y1], [er, x2, y2, z2]]
|
||||
// return [[x, x1, x2], [y, y1, y2], [undefined, undefined, z2]]
|
||||
|
54
node_modules/slide/lib/async-map.js
generated
vendored
Normal file
54
node_modules/slide/lib/async-map.js
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
/*
|
||||
usage:
|
||||
|
||||
// do something to a list of things
|
||||
asyncMap(myListOfStuff, function (thing, cb) { doSomething(thing.foo, cb) }, cb)
|
||||
// do more than one thing to each item
|
||||
asyncMap(list, fooFn, barFn, cb)
|
||||
|
||||
*/
|
||||
|
||||
module.exports = asyncMap
|
||||
|
||||
function asyncMap () {
|
||||
var steps = Array.prototype.slice.call(arguments)
|
||||
, list = steps.shift() || []
|
||||
, cb_ = steps.pop()
|
||||
if (typeof cb_ !== "function") throw new Error(
|
||||
"No callback provided to asyncMap")
|
||||
if (!list) return cb_(null, [])
|
||||
if (!Array.isArray(list)) list = [list]
|
||||
var n = steps.length
|
||||
, data = [] // 2d array
|
||||
, errState = null
|
||||
, l = list.length
|
||||
, a = l * n
|
||||
if (!a) return cb_(null, [])
|
||||
function cb (er) {
|
||||
if (er && !errState) errState = er
|
||||
|
||||
var argLen = arguments.length
|
||||
for (var i = 1; i < argLen; i ++) if (arguments[i] !== undefined) {
|
||||
data[i - 1] = (data[i - 1] || []).concat(arguments[i])
|
||||
}
|
||||
// see if any new things have been added.
|
||||
if (list.length > l) {
|
||||
var newList = list.slice(l)
|
||||
a += (list.length - l) * n
|
||||
l = list.length
|
||||
process.nextTick(function () {
|
||||
newList.forEach(function (ar) {
|
||||
steps.forEach(function (fn) { fn(ar, cb) })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (--a === 0) cb_.apply(null, [errState].concat(data))
|
||||
}
|
||||
// expect the supplied cb function to be called
|
||||
// "n" times for each thing in the array.
|
||||
list.forEach(function (ar) {
|
||||
steps.forEach(function (fn) { fn(ar, cb) })
|
||||
})
|
||||
}
|
16
node_modules/slide/lib/bind-actor.js
generated
vendored
Normal file
16
node_modules/slide/lib/bind-actor.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
module.exports = bindActor
|
||||
function bindActor () {
|
||||
var args =
|
||||
Array.prototype.slice.call
|
||||
(arguments) // jswtf.
|
||||
, obj = null
|
||||
, fn
|
||||
if (typeof args[0] === "object") {
|
||||
obj = args.shift()
|
||||
fn = args.shift()
|
||||
if (typeof fn === "string")
|
||||
fn = obj[ fn ]
|
||||
} else fn = args.shift()
|
||||
return function (cb) {
|
||||
fn.apply(obj, args.concat(cb)) }
|
||||
}
|
20
node_modules/slide/lib/chain.js
generated
vendored
Normal file
20
node_modules/slide/lib/chain.js
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
module.exports = chain
|
||||
var bindActor = require("./bind-actor.js")
|
||||
chain.first = {} ; chain.last = {}
|
||||
function chain (things, cb) {
|
||||
var res = []
|
||||
;(function LOOP (i, len) {
|
||||
if (i >= len) return cb(null,res)
|
||||
if (Array.isArray(things[i]))
|
||||
things[i] = bindActor.apply(null,
|
||||
things[i].map(function(i){
|
||||
return (i===chain.first) ? res[0]
|
||||
: (i===chain.last)
|
||||
? res[res.length - 1] : i }))
|
||||
if (!things[i]) return LOOP(i + 1, len)
|
||||
things[i](function (er, data) {
|
||||
if (er) return cb(er, res)
|
||||
if (data !== undefined) res = res.concat(data)
|
||||
LOOP(i + 1, len)
|
||||
})
|
||||
})(0, things.length) }
|
3
node_modules/slide/lib/slide.js
generated
vendored
Normal file
3
node_modules/slide/lib/slide.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
exports.asyncMap = require("./async-map")
|
||||
exports.bindActor = require("./bind-actor")
|
||||
exports.chain = require("./chain")
|
79
node_modules/slide/package.json
generated
vendored
Normal file
79
node_modules/slide/package.json
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"slide@^1.1.5",
|
||||
"C:\\Users\\x2mjbyrn\\Source\\Repos\\Skeleton\\node_modules\\write-file-atomic"
|
||||
]
|
||||
],
|
||||
"_from": "slide@>=1.1.5-0 <2.0.0-0",
|
||||
"_id": "slide@1.1.6",
|
||||
"_inCache": true,
|
||||
"_location": "/slide",
|
||||
"_npmUser": {
|
||||
"email": "i@izs.me",
|
||||
"name": "isaacs"
|
||||
},
|
||||
"_npmVersion": "2.0.0-beta.3",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "slide",
|
||||
"raw": "slide@^1.1.5",
|
||||
"rawSpec": "^1.1.5",
|
||||
"scope": null,
|
||||
"spec": ">=1.1.5-0 <2.0.0-0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/write-file-atomic"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
|
||||
"_shasum": "56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "slide@^1.1.5",
|
||||
"_where": "C:\\Users\\x2mjbyrn\\Source\\Repos\\Skeleton\\node_modules\\write-file-atomic",
|
||||
"author": {
|
||||
"email": "i@izs.me",
|
||||
"name": "Isaac Z. Schlueter",
|
||||
"url": "http://blog.izs.me/"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/isaacs/slide-flow-control/issues"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "S. Sriram",
|
||||
"email": "ssriram@gmail.com",
|
||||
"url": "http://www.565labs.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {},
|
||||
"description": "A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS",
|
||||
"devDependencies": {},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707",
|
||||
"tarball": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"gitHead": "8345e51ee41e35825abc1a40750ea11462f57028",
|
||||
"homepage": "https://github.com/isaacs/slide-flow-control",
|
||||
"installable": true,
|
||||
"license": "ISC",
|
||||
"main": "./lib/slide.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
}
|
||||
],
|
||||
"name": "slide",
|
||||
"optionalDependencies": {},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/isaacs/slide-flow-control.git"
|
||||
},
|
||||
"scripts": {},
|
||||
"version": "1.1.6"
|
||||
}
|
Reference in New Issue
Block a user