{"_id":"slide","_rev":"25164","name":"slide","description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","dist-tags":{"latest":"1.1.6"},"maintainers":[{"name":"isaacs","email":""}],"time":{"modified":"2021-06-03T10:02:22.000Z","created":"2011-01-13T21:21:32.280Z","1.1.6":"2014-09-12T23:34:41.727Z","1.1.5":"2013-08-19T22:27:46.044Z","1.1.4":"2013-04-29T15:33:13.142Z","1.1.3":"2011-07-27T20:22:03.040Z","1.1.2":"2011-07-20T09:29:21.068Z","1.1.1":"2011-03-17T04:10:26.257Z","1.1.0":"2011-02-03T19:17:03.150Z","1.0.0":"2011-01-13T21:21:32.280Z","1.0.1":"2011-01-13T21:21:32.280Z"},"users":{"agnat":true,"stdarg":true,"matteo.collina":true,"hal9zillion":true,"jian263994241":true,"mattmcfarland":true,"lgomez":true,"gekowa":true,"wangnan0610":true},"author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"repository":{"type":"git","url":"git://github.com/isaacs/slide-flow-control.git"},"versions":{"1.1.6":{"name":"slide","version":"1.1.6","author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"contributors":[{"name":"S. Sriram","email":"ssriram@gmail.com","url":"http://www.565labs.com"}],"description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","main":"./lib/slide.js","dependencies":{},"devDependencies":{},"engines":{"node":"*"},"repository":{"type":"git","url":"git://github.com/isaacs/slide-flow-control.git"},"license":"ISC","gitHead":"8345e51ee41e35825abc1a40750ea11462f57028","bugs":{"url":"https://github.com/isaacs/slide-flow-control/issues"},"homepage":"https://github.com/isaacs/slide-flow-control","_id":"slide@1.1.6","scripts":{},"_shasum":"56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707","_from":".","_npmVersion":"2.0.0-beta.3","_npmUser":{"name":"isaacs","email":"i@izs.me"},"maintainers":[{"name":"isaacs","email":""}],"dist":{"shasum":"56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707","size":4392,"noattachment":false,"key":"/slide/-/slide-1.1.6.tgz","tarball":"http://registry.cnpm.dingdandao.com/slide/download/slide-1.1.6.tgz"},"directories":{},"publish_time":1410564881727,"_cnpm_publish_time":1410564881727,"_hasShrinkwrap":false},"1.1.5":{"name":"slide","version":"1.1.5","author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"contributors":[{"name":"S. Sriram","email":"ssriram@gmail.com","url":"http://www.565labs.com"}],"description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","main":"./lib/slide.js","dependencies":{},"devDependencies":{},"engines":{"node":"*"},"repository":{"type":"git","url":"git://github.com/isaacs/slide-flow-control.git"},"license":"ISC","bugs":{"url":"https://github.com/isaacs/slide-flow-control/issues"},"_id":"slide@1.1.5","dist":{"shasum":"31732adeae78f1d2d60a29b63baf6a032df7c25d","size":4374,"noattachment":false,"key":"/slide/-/slide-1.1.5.tgz","tarball":"http://registry.cnpm.dingdandao.com/slide/download/slide-1.1.5.tgz"},"_from":".","_npmVersion":"1.3.8","_npmUser":{"name":"isaacs","email":"i@izs.me"},"maintainers":[{"name":"isaacs","email":""}],"directories":{},"publish_time":1376951266044,"_hasShrinkwrap":false,"_cnpm_publish_time":1376951266044},"1.1.4":{"name":"slide","version":"1.1.4","author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"contributors":[{"name":"S. Sriram","email":"ssriram@gmail.com","url":"http://www.565labs.com"}],"description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","main":"./lib/slide.js","dependencies":{},"devDependencies":{},"engines":{"node":"*"},"repository":{"type":"git","url":"git://github.com/isaacs/slide-flow-control.git"},"bugs":{"url":"https://github.com/isaacs/slide-flow-control/issues"},"_id":"slide@1.1.4","dist":{"shasum":"2b23f1949b369ed61d22bd6570ff0320302fc8df","size":4542,"noattachment":false,"key":"/slide/-/slide-1.1.4.tgz","tarball":"http://registry.cnpm.dingdandao.com/slide/download/slide-1.1.4.tgz"},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"isaacs","email":"i@izs.me"},"maintainers":[{"name":"isaacs","email":""}],"directories":{},"publish_time":1367249593142,"_hasShrinkwrap":false,"_cnpm_publish_time":1367249593142},"1.1.3":{"name":"slide","version":"1.1.3","author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"contributors":[{"name":"S. Sriram","email":"ssriram@gmail.com","url":"http://www.565labs.com"}],"description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","main":"./lib/slide.js","dependencies":{},"devDependencies":{},"engines":{"node":"*"},"repository":{"type":"git","url":"git://github.com/isaacs/slide-flow-control.git"},"_npmJsonOpts":{"file":"/Users/isaacs/.npm/slide/1.1.3/package/package.json","wscript":false,"contributors":false,"serverjs":false},"_id":"slide@1.1.3","_engineSupported":true,"_npmVersion":"1.0.22","_nodeVersion":"v0.4.10-pre","_defaultsLoaded":true,"dist":{"shasum":"a16975ba76b766b92f98ef337243336c1fa3238f","size":137202,"noattachment":false,"key":"/slide/-/slide-1.1.3.tgz","tarball":"http://registry.cnpm.dingdandao.com/slide/download/slide-1.1.3.tgz"},"scripts":{},"directories":{},"publish_time":1311798123040,"maintainers":[{"name":"isaacs","email":""}],"_hasShrinkwrap":false,"_cnpm_publish_time":1311798123040},"1.1.2":{"name":"slide","version":"1.1.2","author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"contributors":[{"name":"S. Sriram","email":"ssriram@gmail.com","url":"http://www.565labs.com"}],"description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","main":"./lib/slide.js","dependencies":{},"devDependencies":{},"engines":{"node":"*"},"repository":{"type":"git","url":"git://github.com/isaacs/slide-flow-control.git"},"_npmJsonOpts":{"file":"/Users/isaacs/.npm/slide/1.1.2/package/package.json","wscript":false,"contributors":false,"serverjs":false},"_id":"slide@1.1.2","_engineSupported":true,"_npmVersion":"1.0.18","_nodeVersion":"v0.4.10-pre","_defaultsLoaded":true,"dist":{"shasum":"6339e63a65f1d5f6b0ab9a573a6ca276993aad7d","size":140622,"noattachment":false,"key":"/slide/-/slide-1.1.2.tgz","tarball":"http://registry.cnpm.dingdandao.com/slide/download/slide-1.1.2.tgz"},"scripts":{},"directories":{},"publish_time":1311154161068,"maintainers":[{"name":"isaacs","email":""}],"_hasShrinkwrap":false,"_cnpm_publish_time":1311154161068},"1.1.1":{"name":"slide","version":"1.1.1","author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"contributors":[{"name":"S. Sriram","email":"ssriram@gmail.com","url":"http://www.565labs.com"}],"description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","main":"./lib/slide.js","_id":"slide@1.1.1","engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"1.0.0","_nodeVersion":"v0.5.0-pre","directories":{"lib":"./lib"},"_defaultsLoaded":true,"dist":{"shasum":"198afd3d6aab806681924a08e49b5758fb1c49b6","size":140000,"noattachment":false,"key":"/slide/-/slide-1.1.1.tgz","tarball":"http://registry.cnpm.dingdandao.com/slide/download/slide-1.1.1.tgz"},"publish_time":1300335026257,"maintainers":[{"name":"isaacs","email":""}],"_hasShrinkwrap":false,"_cnpm_publish_time":1300335026257},"1.1.0":{"name":"slide","version":"1.1.0","author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"contributors":[{"name":"S. Sriram","email":"ssriram@gmail.com","url":"http://www.565labs.com"}],"description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","main":"./lib/slide","_id":"slide@1.1.0","engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"0.2.17","_nodeVersion":"v0.3.8-pre","directories":{"lib":"./lib"},"files":[""],"_defaultsLoaded":true,"dist":{"shasum":"a9e135aa14bf5bb8b8c9e16c723c7223ac30f717","size":140209,"noattachment":false,"key":"/slide/-/slide-1.1.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/slide/download/slide-1.1.0.tgz"},"publish_time":1296760623150,"maintainers":[{"name":"isaacs","email":""}],"_hasShrinkwrap":false,"_cnpm_publish_time":1296760623150},"1.0.0":{"name":"slide","version":"1.0.0","author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","directories":{"lib":"lib"},"_id":"slide@1.0.0","engines":{"node":"*"},"_nodeSupported":true,"_npmVersion":"0.2.7-2","_nodeVersion":"v0.3.1-pre","dist":{"shasum":"c3842da5e075b83eb68864c3fa64d752121b17f1","size":5463,"noattachment":false,"key":"/slide/-/slide-1.0.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/slide/download/slide-1.0.0.tgz"},"publish_time":1294953692280,"maintainers":[{"name":"isaacs","email":""}],"_hasShrinkwrap":false,"_cnpm_publish_time":1294953692280},"1.0.1":{"name":"slide","version":"1.0.1","author":{"name":"Isaac Z. Schlueter","email":"i@izs.me","url":"http://blog.izs.me/"},"contributors":[{"name":"S. Sriram","email":"ssriram@gmail.com","url":"http://www.565labs.com"}],"description":"A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS","directories":{"lib":"lib"},"_id":"slide@1.0.1","engines":{"node":"*"},"_engineSupported":true,"_npmVersion":"0.2.14-6","_nodeVersion":"v0.3.5-pre","modules":{"b/async-map.js":"lib/async-map.js","b/bind-actor.js":"lib/bind-actor.js","b/chain.js":"lib/chain.js"},"files":[""],"_defaultsLoaded":true,"dist":{"shasum":"b7d9076eee798237666e66e3f18157532b297f32","size":140022,"noattachment":false,"key":"/slide/-/slide-1.0.1.tgz","tarball":"http://registry.cnpm.dingdandao.com/slide/download/slide-1.0.1.tgz"},"publish_time":1294953692280,"maintainers":[{"name":"isaacs","email":""}],"_hasShrinkwrap":false,"_cnpm_publish_time":1294953692280}},"readme":"# Controlling Flow: callbacks are easy\n\n## What's actually hard?\n\n- Doing a bunch of things in a specific order.\n- Knowing when stuff is done.\n- Handling failures.\n- Breaking up functionality into parts (avoid nested inline callbacks)\n\n\n## Common Mistakes\n\n- Abandoning convention and consistency.\n- Putting all callbacks inline.\n- Using libraries without grokking them.\n- Trying to make async code look sync.\n\n## Define Conventions\n\n- Two kinds of functions: *actors* take action, *callbacks* get results.\n- Essentially the continuation pattern. Resulting code *looks* similar\n  to fibers, but is *much* simpler to implement.\n- Node works this way in the lowlevel APIs already, and it's very ﬂexible.\n\n## Callbacks\n\n- Simple responders\n- Must always be prepared to handle errors, that's why it's the first argument.\n- Often inline anonymous, but not always.\n- Can trap and call other callbacks with modified data, or pass errors upwards.\n\n## Actors\n\n- Last argument is a callback.\n- If any error occurs, and can't be handled, pass it to the callback and return.\n- Must not throw. Return value ignored.\n- return x ==> return cb(null, x)\n- throw er ==> return cb(er)\n\n```javascript\n// return true if a path is either\n// a symlink or a directory.\nfunction isLinkOrDir (path, cb) {\n  fs.lstat(path, function (er, s) {\n    if (er) return cb(er)\n    return cb(null, s.isDirectory() || s.isSymbolicLink())\n  })\n}\n```\n\n# asyncMap\n\n## Usecases\n\n- I have a list of 10 files, and need to read all of them, and then continue when they're all done.\n- I have a dozen URLs, and need to fetch them all, and then continue when they're all done.\n- I have 4 connected users, and need to send a message to all of them, and then continue when that's done.\n- 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.\n\n\n## Solution\n\n```javascript\nvar asyncMap = require(\"slide\").asyncMap\nfunction writeFiles (files, what, cb) {\n  asyncMap(files, function (f, cb) {\n    fs.writeFile(f, what, cb)\n  }, cb)\n}\nwriteFiles([my, file, list], \"foo\", cb)\n```\n\n# chain\n\n## Usecases\n\n- I have to do a bunch of things, in order. Get db credentials out of a file,\n  read the data from the db, write that data to another file.\n- If anything fails, do not continue.\n- I still have to provide an array of functions, which is a lot of boilerplate,\n  and a pita if your functions take args like\n\n```javascript\nfunction (cb) {\n  blah(a, b, c, cb)\n}\n```\n\n- Results are discarded, which is a bit lame.\n- No way to branch.\n\n## Solution\n\n- reduces boilerplate by converting an array of [fn, args] to an actor\n  that takes no arguments (except cb)\n- A bit like Function#bind, but tailored for our use-case.\n- bindActor(obj, \"method\", a, b, c)\n- bindActor(fn, a, b, c)\n- bindActor(obj, fn, a, b, c)\n- branching, skipping over falsey arguments\n\n```javascript\nchain([\n  doThing && [thing, a, b, c]\n, isFoo && [doFoo, \"foo\"]\n, subChain && [chain, [one, two]]\n], cb)\n```\n\n- tracking results: results are stored in an optional array passed as argument,\n  last result is always in results[results.length - 1].\n- treat chain.first and chain.last as placeholders for the first/last\n  result up until that point.\n\n\n## Non-trivial example\n\n- Read number files in a directory\n- Add the results together\n- Ping a web service with the result\n- Write the response to a file\n- Delete the number files\n\n```javascript\nvar chain = require(\"slide\").chain\nfunction myProgram (cb) {\n  var res = [], last = chain.last, first = chain.first\n  chain([\n    [fs, \"readdir\", \"the-directory\"]\n  , [readFiles, \"the-directory\", last]\n  , [sum, last]\n  , [ping, \"POST\", \"example.com\", 80, \"/foo\", last]\n  , [fs, \"writeFile\", \"result.txt\", last]\n  , [rmFiles, \"./the-directory\", first]\n  ], res, cb)\n}\n```\n\n# Conclusion: Convention Profits\n\n- Consistent API from top to bottom.\n- Sneak in at any point to inject functionality. Testable, reusable, ...\n- When ruby and python users whine, you can smile condescendingly.\n","_attachments":{},"homepage":"https://github.com/isaacs/slide-flow-control","bugs":{"url":"https://github.com/isaacs/slide-flow-control/issues"},"license":"ISC"}