9

I'm simply trying to wait for a user to enter a password and then use it before moving on the rest of my code. The error is Cannot read property 'then' of undefined.

let rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.question('Password: ', password => {
    rl.close();
    return decrypt(password);
}).then(data =>{
    console.log(data);
});

function decrypt( password ) {
    return new Promise((resolve) => {
        //do stuff
        resolve(data);
    });
}
yeputons
  • 8,478
  • 34
  • 67
Dustin Raimondi
  • 383
  • 1
  • 4
  • 10
  • 1
    It looks like `rl.question` does not return promise in vanilla Node.Js (I'm assuming the question is about node.js). Actually, it returns nothing, see [source code](https://github.com/nodejs/node/blob/b869ecaacfdd218e1920f1545a88a4304efd0288/lib/readline.js#L217-L228). So I'd expect that there is no `then` method on it. So if you really need a promise, I think you'll have to implement it manually. – yeputons Feb 07 '17 at 02:27

2 Answers2

4

Readline's question() function does not return Promise or result of the arrow function. So, you cannot use then() with it. You could simply do

rl.question('Password: ', (password) => {
    rl.close();
    decrypt(password).then(data => {
       console.log(data);
    });
});

If you really need to build a chain with Promise, you can compose your code differently:

new Promise((resolve) => {
    rl.question('Password: ', (password) => {
        rl.close();
        resolve(password);
    });
}).then((password) => {
   return decrypt(password); //returns Promise
}).then((data) => {
   console.log(data); 
});

You probably should not forget about the .catch(), otherwise either solution works, the choice should be based on which code will be easier to read.

You may want to look at a couple of additional promise usage patterns

Alex Pakka
  • 9,466
  • 3
  • 45
  • 69
  • No, you should never use `async.js` with promises. Use the helper functions from your promise library, nothing callback-based. – Bergi Feb 07 '17 at 04:47
  • @Bergi - you are right; if you have to use Promises literally, async.js is a bad idea, since it's all callbacks. I just wanted to point to certain semantics there, but maybe it's confusing rather then helpful. Myself I ended up creating couple of monadic constructs on top of Promise to deal with missing functionality in Promise/A+. I will edit the answer to point to a more helpful resource. – Alex Pakka Feb 07 '17 at 16:55
  • I accepted this answer because it was correct, and then ended up switching from readline to prompt-promise to get the desired code flow. – Dustin Raimondi Feb 11 '17 at 00:55
2

And if you are scared of using callbacks and the possibility of callback hell. You can check readline-sync package

Femi Oladeji
  • 365
  • 2
  • 7