0

I used async and await to achieve this but somehow the 2nd function gets called without even waiting for the 1st function to complete.

Is async and await best way to do this?

In this case do I need to call 1st function inside of second function or can it be called inside init function one after the other?

const prompt = require('prompt');
const properties = [
    {
        name: 'module_name',
        default: 'custom-module',
        description: "Name your Application module",
        type: 'string'
    },
    {
        name: 'application_home',
        description: "Provide Application Home location (absolute path)",
        message: "Your Application Home location should be a clone of Application Github repo and should have package.json",
        type: 'string',
        required: true
    }
];
let module_name;
let application_home;

/**Prompt user to get mandatory details */
const getModuleDetails = async () => {
    prompt.start();
    prompt.get(properties, function (err, result) {
        if (err) { return onErr(err); }
        module_name = result.module_name;
        application_home = result.application_home;
        return;
    });
}

/**Verbose */
const verboseDetails = async () => {
    await getModuleDetails()
    console.log('Command-line input received:');
    console.log('Module Name: ' + module_name);
    console.log('Application Home location: ' + application_home);
}

const init = async () => {
    //getModuleDetails();
    await verboseDetails();
}

init();

Response enter image description here

Update

/**Prompt user to get mandatory details */
const getModuleDetails = async () => {
    prompt.start();
    const result = await prompt.get(properties);
    module_name = result.module_name;
    application_home = result.application_home;
}

const verboseDetails = async () => {
    console.log('Command-line input received:');
    console.log('Module Name: ' + module_name);
    console.log('Botpress Home location: ' + application_home);
}

const init = async () => {
    await getModuleDetails();
    await verboseDetails();
}

init();
Ricky
  • 314
  • 1
  • 7
  • 22
  • @Vega: I updated the question with changes after following Alnitak solution (not working). Once I have a working solution I will update my question. – Ricky Aug 24 '20 at 10:56
  • 1
    @Ricky my solution _does_ work if you use the latest code from git, not the 1.0.0 release. You might consider using an alternate library that's better maintained... – Alnitak Aug 25 '20 at 08:51

4 Answers4

3

Use the promise, Luke

const prompt = require('prompt');
const properties = [{
        name: 'module_name',
        default: 'custom-module',
        description: "Name your Application module",
        type: 'string'
    },
    {
        name: 'application_home',
        description: "Provide Application Home location (absolute path)",
        message: "Your Application Home location should be a clone of Application Github repo and should have package.json",
        type: 'string',
        required: true
}];
let module_name;
let application_home;

/**Prompt user to get mandatory details */
const getModuleDetails = async () => new Promise((resolve, reject) => {
    prompt.start();
    prompt.get(properties, function (err, result) {
        if (err) {  reject(err); } else {
          module_name = result.module_name;
          application_home = result.application_home;
          resolve(result);
        }
    });
})

/**Verbose */
const verboseDetails = async () => {
    await getModuleDetails()
    console.log('Command-line input received:');
    console.log('Module Name: ' + module_name);
    console.log('Application Home location: ' + application_home);
}

const init = async () => {
    //getModuleDetails();
    await verboseDetails();
}

init();
Darth
  • 1,592
  • 10
  • 19
0

I would suggest using a Promise.

A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.

Here's a MDN article describing how it works, and how to use it:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Yoni Ziv
  • 166
  • 1
  • 10
0

You can use util.promisify to make prompt.get return a Promise that you can await in order to maintain the required execution sequence:

const util = require('util');

let module_name;
let application_home;

const getModuleDetails = async () => {
  prompt.start();
  const result = await util.promisify(prompt.get)(properties);
  module_name = result.module_name;
  application_home = result.application_home;
}
antonku
  • 7,377
  • 2
  • 15
  • 21
  • the current git release of prompt already supports promises. – Alnitak Aug 24 '20 at 09:08
  • @Alnitak Yes, but this would require to download the package from github directly. This means pinning the package version to a branch or commit negating semver benefits – antonku Aug 24 '20 at 09:22
  • when a package is abandonware that's sometimes the choice you have to make – Alnitak Aug 24 '20 at 09:39
0

You are not waiting for the result of the prompt.

The prompt library also supports async - use:

const result = await prompt.get(properties);

instead of the callback pattern.

However you will need to specifically request the latest version from git in your package.json file. The last release from NPM is 5 years old:

"dependencies": {
  "prompt": "git+https://git@github.com/flatiron/prompt.git"
}
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • It did not work. Updated my question with latest try code. package.json already contains prompt v1.0.0. – Ricky Aug 24 '20 at 09:28
  • Did you see the note where I said you'll need to specify the `git` path instead of using `npm`? – Alnitak Aug 24 '20 at 09:36