I want to ask questions to the user without having all the questions lined up immediately.
The documentation mentions rxjs but I feel there is a gap in the documentation on how to properly add questions while prompts are being executed, or at least it did not quite work for me.
https://www.npmjs.com/package/inquirer#reactive-interface
Internally, Inquirer uses the JS reactive extension to handle events and async flows.
This mean you can take advantage of this feature to provide more advanced flows. For example, you can dynamically add questions to be asked:
var prompts = new Rx.Subject();
inquirer.prompt(prompts);
// At some point in the future, push new questions
prompts.next({
/* question... */
});
prompts.next({
/* question... */
});
// When you're done
prompts.complete();
And using the return value process property, you can access more fine grained callbacks:
inquirer.prompt(prompts).ui.process.subscribe(onEachAnswer, onError, onComplete);
So thanks to some inspiration from this blog post by jana e. beck, I made the code I needed. The examples and tips from jana was a little out of date, where using Subject from rxjs would no longer work for some reason, at least it did not work for me. This was easily fixed however by storing the emitter outside the Observer creation callback. Remember to add rxjs as a dependency to your project (same as the one InquirerJS is currently using probably helps).
const inquirer = require("inquirer");
var { Observable } = require("rxjs");
let emitter;
var prompts = Observable.create(function(e) {
emitter = e;
// need to start with at least one question here
emitter.next({
type: "list",
name: "fruits",
message: "What is your favorite fruit?",
choices: [
{
name: "Banana"
},
{
name: "Apple"
},
{
name: "Pear"
}
]
});
});
let times = 0;
inquirer.prompt(prompts).ui.process.subscribe(
q => {
let dots = new Array(times).fill(".").join("");
if (q.answer.toLowerCase() === "pear") {
console.log("That's Great. I would never forget a Pear-eater.");
emitter.complete();
}
emitter.next({
type: "list",
name: "fruits",
message:
"Sorry, what is your favorite fruit? I forgot, was it " +
q.answer +
", or something else?",
choices: [
{
name: "Uh, Banana.." + dots,
value: "banana"
},
{
name: "Uh, Apple.." + dots,
value: "apple"
},
{
name: "Pear!",
value: "pear"
}
]
});
times++;
},
error => {
console.log("Hm, an error happened. Why?");
},
complete => {
console.log("I think we are done now.");
}
);
This prompt along with the blog post should be what you need to get started. Remember that you can queue up multiple questions in one go, should you want to.
When you are done, you put emitter.complete();
somewhere to end the prompt.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With