# slide

> A flow control lib small enough to fit on in a slide presentation. Derived live at Oak.JS

Latest version **1.1.6** (published 2014-09-12) · ISC license · 0 weekly downloads

## Install

```sh
npm install slide
pnpm add slide
yarn add slide
bun add slide
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.1.6 |
| Published | 2014-09-12 |
| First published | 2011-01-13 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Node | * |
| Dependencies | 0 |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Isaac Z. Schlueter |
| Maintainers | isaacs |

## Links

- npm: https://www.npmjs.com/package/slide
- Repository: https://github.com/isaacs/slide-flow-control
- Issues: https://github.com/isaacs/slide-flow-control/issues
- npm.io page: https://npm.io/package/slide

## Recent versions

- 1.1.6 (latest) — 2014-09-12
- 1.1.5 — 2013-08-19
- 1.1.4 — 2013-04-29
- 1.1.3 — 2011-07-27
- 1.1.2 — 2011-07-20
- 1.1.1 — 2011-03-17
- 1.1.0 — 2011-02-03
- 1.0.0 — 2011-01-13
- 1.0.1 — 2011-01-13

## README

# 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 ﬂexible.

## 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.

---
_Source: https://npm.io/package/slide · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
