New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

flow-maintained

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

flow-maintained - npm Package Compare versions

Comparing version 0.2.3 to 0.2.4

39

package.json
{
"name" : "flow-maintained",
"description" : "Flow-JS makes it easy to express multi-step asynchronous logic in Node or the browser; maintained by Celtra",
"url" : "http://github.com/willconant/flow-js",
"keywords" : ["util", "functional", "server", "client", "browser"],
"author" : "Will Conant <will.conant@gmail.com>",
"contributors" : [],
"dependencies" : {},
"lib" : ".",
"main" : "flow.js",
"version" : "0.2.3"
"name": "flow-maintained",
"description": "Flow-JS makes it easy to express multi-step asynchronous logic in Node or the browser; maintained by Celtra",
"url": "http://github.com/willconant/flow-js",
"repository": {
"type": "git",
"url": "https://github.com/willconant/flow-js.git"
},
"keywords": [
"util",
"functional",
"server",
"client",
"browser"
],
"author": {
"name": "Will Conant",
"email": "will.conant@gmail.com"
},
"contributors": [],
"dependencies": {},
"lib": ".",
"main": "flow.js",
"version": "0.2.4",
"readme": "Flow-JS\n===============\n\nOverview\n---------------\n\nFlow-JS provides a continuation-esque construct that makes it much easier to express\nmulti-step asynchronous logic in non-blocking callback-heavy environments like\nNode.js or javascript in the web browser.\n\nThe concept is best explained with an example. The following code uses a simple\nasynchronous key-store to look-up a user's ID from his username and then sets his\nemail address, first name, and last name.\n\nIn this example, the dbGet and dbSet functions are assumed to rely on asynchronous\nI/O and both take a callback that is called upon completion.\n\n\tdbGet('userIdOf:bobvance', function(userId) {\n\t\tdbSet('user:' + userId + ':email', 'bobvance@potato.egg', function() {\n\t\t\tdbSet('user:' + userId + ':firstName', 'Bob', function() {\n\t\t\t\tdbSet('user:' + userId + ':lastName', 'Vance', function() {\n\t\t\t\t\tokWeAreDone();\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t});\n\nNotice how every single step requires another nested function definition. A\nfour-step process like the one shown here is fairly awkward. Imagine how painful a\n10-step process would be!\n\nOne might point out that there is no reason to wait for one dbSet to complete before\ncalling the next, but, assuming we don't want okWeAreDone to be called until all\nthree calls to dbSet are finished, we'd need some logic to manage that:\n\n\tdbGet('userIdOf:bobvance', function(userId) {\n\t\tvar completeCount = 0;\n\t\tvar complete = function() {\n\t\t\tcompleteCount += 1;\n\t\t\tif (completeCount == 3) {\n\t\t\t\tokWeAreDone();\n\t\t\t}\n\t\t}\n\t\t\n\t\tdbSet('user:' + userId + ':email', 'bobvance@potato.egg', complete);\n\t\tdbSet('user:' + userId + ':firstName', 'Bob', complete);\n\t\tdbSet('user:' + userId + ':lastName', 'Vance', complete);\n\t});\n\nNow look at the same example using Flow-JS:\n\n\tflow.exec(\n\t\tfunction() {\n\t\t\tdbGet('userIdOf:bobvance', this);\n\t\t\t\n\t\t},function(userId) {\n\t\t\tdbSet('user:' + userId + ':email', 'bobvance@potato.egg', this.MULTI());\n\t\t\tdbSet('user:' + userId + ':firstName', 'Bob', this.MULTI());\n\t\t\tdbSet('user:' + userId + ':lastName', 'Vance', this.MULTI());\n\t\t\n\t\t},function() {\n\t\t\tokWeAreDone()\n\t\t}\n\t);\n\nA flow consists of a series of functions, each of which is applied with a special\n`this` object which serves as a callback to the next function in the series. In\ncases like our second step, `this.MULTI()` can be used to generate a callback that\nwon't call the next function until all such callbacks have been called.\n\n\nInstalling\n---------------\n\nFlow-JS is a CommonJS compatible module. Place the \"flow.js\" file in any directory\nlisted in your `require.paths` array and require it like this:\n\n\tvar flow = require('flow')\n\nOr you can just put \"flow.js\" next to your script and do this:\n\n\tvar flow = require('./flow')\n\n\nDefining a Flow\n---------------\n\n`flow.define` defines a flow given any number of functions as parameters. It returns\na function that can be used to execute that flow more than once. Whatever parameters\nare passed each time that flow is called are passed as the parameters to the first\nfunction in the flow.\n\nEach function in the flow is called with a special `this` object which maintains the\nstate of the flow's execution, acts as a container for saving values for use between\nfunctions in the flow, and acts as a callback to the next function in the flow.\n\nHere is an example to make this clear:\n\n\t// define a flow for renaming a file and then printing its stats\n\tvar renameAndStat = flow.define(\n\t\n\t\tfunction(fromName, toName) {\n\t\t\t// arguments passed to renameAndStat() will pass through to this first function\n\t\t\t\n\t\t\tthis.toName = toName; // save to be used in the next function\n\t\t\tfs.rename(fromName, toName, this);\n\t\t\n\t\t},function(err) {\n\t\t\t// when fs.rename calls the special \"this\" callback above, this function will be called\n\t\t\t// whatever arguments fs.rename chooses to pass to the callback will pass through to this function\n\t\t\n\t\t\tif (err) throw err;\n\t\t\t\n\t\t\t// the \"this\" here is the same as in the function above, so this.toName is available\n\t\t\tfs.stat(this.toName, this);\n\t\t\n\t\t},function(err, stats) {\n\t\t\t// when fs.stat calls the \"this\" callback above, this function will be called\n\t\t\t// whatever arguments fs.stat chooses to pass to the callback will pass through to this function\n\t\t\t\n\t\t\tif (err) throw err;\n\t\t\t\n\t\t\tsys.puts(\"stats: \" + JSON.stringify(stats));\n\t\t}\n\t);\n\t\n\t// now renameAndStat can be used more than once\n\trenameAndStat(\"/tmp/hello1\", \"/tmp/world1\");\n\trenameAndStat(\"/tmp/hello2\", \"/tmp/world2\");\n\n\nExecuting a Flow Just Once\n---------------\n\n`flow.exec` is a convenience function that defines a flow and executes it immediately,\npassing no arguments to the first function.\n\nHere's a simple example very similar to the one above:\n\n\tflow.exec(\n\t\tfunction() {\n\t\t\tfs.rename(\"/tmp/hello\", \"/tmp/world\", this);\n\t\t},function(err) {\n\t\t\tif (err) throw err;\n\t\t\tfs.stat(\"/tmp/world\", this)\n\t\t},function(err, stats) {\n\t\t\tif (err) throw err;\n\t\t\tsys.puts(\"stats: \" + JSON.stringify(stats));\n\t\t}\n\t);\n\n\nMultiplexing\n---------------\n\nSometimes, it makes sense for a step in a flow to initiate several asynchronous tasks and\nthen wait for all of those tasks to finish before continuing to the next step in the flow.\nThis can be accomplished by passing `this.MULTI()` as the callback rather than just `this`.\n\nHere is an example of `this.MULTI()` in action (repeated from the overview):\n\n\tflow.exec(\n\t\tfunction() {\n\t\t\tdbGet('userIdOf:bobvance', this);\n\t\t\t\n\t\t},function(userId) {\n\t\t\tdbSet('user:' + userId + ':email', 'bobvance@potato.egg', this.MULTI());\n\t\t\tdbSet('user:' + userId + ':firstName', 'Bob', this.MULTI());\n\t\t\tdbSet('user:' + userId + ':lastName', 'Vance', this.MULTI());\n\t\t\n\t\t},function() {\n\t\t\tokWeAreDone()\n\t\t}\n\t);\n\n You can identify the results of a function by passing a result identifier to MULTI. The results of a function can retrieved using this key in the final step. The result will be a single value if callback receives 0 or 1 argument, otherwise it will be an array of arguments passed to the callback.\n\n Example:\n\n\tflow.exec(\n\t\tfunction() {\n\t\t\tdbGet('userIdOf:bobvance', this.MULTI('bob'));\n\t\t\tdbGet('userIdOf:joohndoe', this.MULTI('john'));\n\t\t},function(results) {\n\t\t dbSet('user:' + results['bob'] + ':email', 'bobvance@potato.egg');\n\t\t dbSet('user:' + results['john'] + ':email', 'joohndoe@potato.egg');\n\t\t okWeAreDone();\n\t\t}\n\t);\n\nIn many cases, you may simply discard the arguments passed to each of the callbacks generated\nby `this.MULTI()`, but if you need them, they are accessible as an array of `arguments`\nobjects passed as the first argument of the next function. Each `arguments` object will be\nappended to the array as it is received, so the order will be unpredictable for most\nasynchronous APIs.\n\nHere's a quick example that checks for errors:\n\n\tflow.exec(\n\t\tfunction() {\n\t\t\tfs.rename(\"/tmp/a\", \"/tmp/1\", this.MULTI());\n\t\t\tfs.rename(\"/tmp/b\", \"/tmp/2\", this.MULTI());\n\t\t\tfs.rename(\"/tmp/c\", \"/tmp/3\", this.MULTI());\n\t\t\n\t\t},function(argsArray) {\n\t\t\targsArray.forEach(function(args){\n\t\t\t\tif (args[0]) then throw args[0];\n\t\t\t});\n\t\t}\n\t);\n\n\nserialForEach\n---------------\n\nFlow-JS comes with a convience function called `flow.serialForEach` which can be used to\napply an asynchronous function to each element in an array of values serially:\n\n\tflow.serialForEach([1, 2, 3, 4], function(val) {\n\t\tkeystore.increment(\"counter\", val, this);\n\t},function(error, newVal) {\n\t\tif (error) throw error;\n\t\tsys.puts('newVal: ' + newVal);\n\t},function() {\n\t\tsys.puts('This is the end!');\n\t});\n\n`flow.serialForEach` takes an array-like object, a function to be called for each item\nin the array, a function that receives the callback values after each iteration, and a\nfunction that is called after the entire process is finished. Both of the second two\nfunctions are optional.\n\n`flow.serialForEach` is actually implemented with `flow.define`.\n\nThanks to John Wright for suggesting the idea! (http://github.com/mrjjwright)\n",
"readmeFilename": "README.md",
"_id": "flow-maintained@0.2.3",
"_shasum": "bdcfb9f989aa1a63419dd25b608179c393961fe8",
"_from": "flow-maintained@0.2.3",
"_resolved": "https://registry.npmjs.org/flow-maintained/-/flow-maintained-0.2.3.tgz"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc