Permalink
Browse files

Support prompt() in async functions as well

  • Loading branch information...
1 parent 2dfbe1e commit 942194eee73f4b8b5f58442e20f079401cdf74b3 @isaacs isaacs committed Jun 17, 2012
Showing with 55 additions and 3 deletions.
  1. +41 −0 README.md
  2. +3 −0 promzard.js
  3. +3 −0 test/fn.input
  4. +8 −3 test/fn.js
View
@@ -87,3 +87,44 @@ whatever needs verification.
The functions are called in the context of the ctx object, and are given
a single argument, which is a callback that should be called with either
an error, or the result to assign to that spot.
+
+In the async function, you can also call prompt() and return the result
+of the prompt in the callback.
+
+For example, this works fine in a promzard module:
+
+```
+exports.asyncPrompt = function (cb) {
+ fs.stat(someFile, function (er, st) {
+ // if there's an error, no prompt, just error
+ // otherwise prompt and use the actual file size as the default
+ cb(er, prompt('file size', st.size))
+ })
+}
+```
+
+You can also return other async functions in the async function
+callback. Though that's a bit silly, it could be a handy way to reuse
+functionality in some cases.
+
+### Sync vs Async
+
+The `prompt()` function is not synchronous, though it appears that way.
+It just returns a token that is swapped out when the data object is
+walked over asynchronously later, and returns a token.
+
+For that reason, prompt() calls whose results don't end up on the data
+object are never shown to the user. For example, this will only prompt
+once:
+
+```
+exports.promptThreeTimes = prompt('prompt me once', 'shame on you')
+exports.promptThreeTimes = prompt('prompt me twice', 'um....')
+exports.promptThreeTimes = prompt('you cant prompt me again')
+```
+
+### Isn't this exactly the sort of 'looks sync' that you said was bad about other libraries?
+
+Yeah, sorta. I wouldn't use promzard for anything more complicated than
+a wizard that spits out prompts to set up a config file or something.
+Maybe there are other use cases I haven't considered.
View
@@ -182,6 +182,9 @@ PromZard.prototype.walk = function (o, cb) {
if (er)
return this.emit('error', this.error = er)
o[k] = res
+ // back up so that we process this one again.
+ // this is because it might return a prompt() call in the cb.
+ i --
L.call(this)
}.bind(this))
}
View
@@ -11,5 +11,8 @@ module.exports = {
},
a_function: function (cb) {
fs.readFile(__filename, 'utf8', cb)
+ },
+ asyncPrompt: function (cb) {
+ return cb(null, prompt('a prompt at any other time would smell as sweet'))
}
}
View
@@ -4,7 +4,7 @@ var fs = require('fs')
test('prompt callback param', function (t) {
t.plan(1);
-
+
var ctx = { tmpdir : '/tmp' }
var file = __dirname + '/fn.input';
promzard(file, ctx, function (err, output) {
@@ -18,17 +18,22 @@ test('prompt callback param', function (t) {
}
}
expect.a_function = fs.readFileSync(file, 'utf8')
+ expect.asyncPrompt = 'async prompt'
t.same(
output,
expect
);
});
-
+
setTimeout(function () {
process.stdin.emit('data', '\n');
}, 100);
-
+
setTimeout(function () {
process.stdin.emit('data', '55\n');
}, 200);
+
+ setTimeout(function () {
+ process.stdin.emit('data', 'async prompt')
+ }, 300)
});

0 comments on commit 942194e

Please sign in to comment.