Home > database >  Why do my other methods run before the prompt-list selection is done?
Why do my other methods run before the prompt-list selection is done?

Time:02-23

I'm currently working on a proof-of-concept for a web app that will be used by two users. For this, I'm simulating the process within the terminal (very very basic).

What I'm trying to do is to demonstrate the initial "linking" of the two users. I've created a class for the users with multiple properties. The method setUserInfo() should run step-by-step until the user selects a preference of my list (I'm using the prompt-list npm package for this) and then this selection should be pushed into the array ownPref. After that the method receivePartnerPrefs() should insert the contents of partnerExamplePrefs into the constructor property partnerPrefs.

The problem is, if I run this script, everything is fine until the list.ask() method of the prompt-list package does its thing. Every method after that (in this case receivePartnerPrefs) runs simultaneously and breaks the step-by-step process I'm trying to show here.

const prompt = require("prompt-sync")();
var List = require("prompt-list");

let partnerExamplePrefs = [
  "Farbenfroh",
  "Eng geschnitten",
  "Schlicht und einfach",
];

let prefs = [];

class User {
  constructor(userName, ownPref = [], socPoints, shopPartner, partnerPrefs) {
    this.userName = userName;
    this.ownPref = ownPref;
    this.socPoints = socPoints;
    this.shopPartner = shopPartner;
    this.partnerPrefs = partnerPrefs;
  }

  setUserInfo() {
    this.userName = prompt("Hallo! Wie ist dein Name? ");
    console.log("Hallo "   this.userName);

    this.socPoints = 0;

    this.shopPartner = prompt(
      "Wen möchtest du als Shopping Begleitung wählen? "
    );
    console.log(this.shopPartner   " und du seid nun verlinkt!");

    var list = new List({
      name: "preferences",
      message:
        "Damit deine Shopping-Begleitungen für dich Produkte auswählen können, benötigt sie ein paar Informationen. Bitte wähle aus der folgenden Liste einen Punkt aus, der dir am Wichtigsten ist: ",
      choices: [
        "Farbenfroh",
        "Schwarz-weiß",
        "Eng geschnitten",
        "Weit geschnitten",
        "Schlicht und einfach",
        "Ausgefallenes",
      ],
    });

    list.ask(function (answer) {
      this.ownPref = prefs;
      this.ownPref.push(answer);
    });
  }

  receivePartnerPrefs() {
    // Receive partner preferences
    this.partnerPrefs = partnerExamplePrefs;

    console.log(
      "Die Vorlieben von "  
        this.shopPartner  
        " wurden übertragen. Sämtliche Produkte die du sehen wirst, basieren auf den Vorlieben deines Partners. Nun kannst du beginnen dich mit deiner Begleitung auseinanderzusetzen!"
    );
  }
}

let myUser = new User();
myUser.setUserInfo();
myUser.receivePartnerPrefs();

Where is my error in this? Thanks!

CodePudding user response:

Looking at the readme of the prompt-list:

// async
list.ask(function(answer) {
  console.log(answer);
});
 
// promise
list.run()
  .then(function(answer) {
    console.log(answer);
  });

ask is an async function. It does its thing while other parts of the app continue running. If you want to wait until the task is finished, you can either do the rest of what you want to do inside the callback function, or use the other method (list.run()) and wait for the promise to be resolved before proceeding.

For that, you'll need to make setUserInfo method an async method. async methods return a Promise by design which is resolved when the execution of the method is done. In that method, you also need to await on list.run().

Then, you'll need to put the main part of your code inside an async function too, so you could await on the setUserInfo() method.

Notice that you can also get away with just calling the method and using .then notation to do things only after the promise is resolved, but await makes things more readable.

class User {
  constructor(...) {
    // ...
  }

  async setUserInfo() {
    // ...
    var list = new List({
      // ...
    });

    const answer = await list.run();

    this.ownPref = prefs;
    this.ownPref.push(answer);
  }

  receivePartnerPrefs() {
    // ...
  }
}

const main = async () => {
  let myUser = new User();
  await myUser.setUserInfo();
  myUser.receivePartnerPrefs();
};

main().catch(console.error);
  • Related