JbSel
JbSel

Reputation: 13

NodeJS Class Method Asynchronous return

I am currently writing a class in JavaScript with a login method.

const EventEmitter = require('events');
const util = require('util');
const Settings = require('./config');
const config = new Settings();
const http = require('request');

class Client extends EventEmitter {

constructor(username, password) {
    super();
    this.username = username;
    this.password = password;
}

get login() {
    return this.login();
}



login() {
    http.post({
      url:     config.host + "v" + config.version + "/method/account.signIn.inc.php",
      body:    "username="+ this.username + "&password=" + this.password + "&clientid=" + config.clientid
    }, function(error, response, body){
      return body;
    });
  }
}

module.exports = Client;

I am using the request module to make HTTP requests but request is using asynchronous calls and I am always getting undefined when calling console.log(client.login()); from another file. I have seen many solutions targeting asynchronous calls with callbacks, but I cant seem to figure it out with callbacks or promises within a class.

Upvotes: 1

Views: 91

Answers (2)

Mark
Mark

Reputation: 92440

There are a lot of ways to do this — callbacks, events, promises. Most people tend to like the solutions with promises and this is a good use case for them. With promises you can do something like this:

login() {
    return new Promise((resolve, reject) => {
        http.post({
        url: config.host + "v" + config.version + "/method/account.signIn.inc.php",
        body: "username="+ this.username + "&password=" + this.password + "&clientid=" + config.clientid
        }, function(error, response, body){
            if (error) return reject(error)
            resolve(body);
        });
    })
}

Then you can call it:

let client = new Client(username, password)
client.login()
.then(result => {
   // result available here
})
.catch(err => {
    // an error 
})

Having said that, it also looks like you are defining the class as a subclass of EventEmitter, which suggests you want to use events. You can also use this to indicate the login with something like:

login() {
    http.post({
    url:     config.host + "v" + config.version + "/method/account.signIn.inc.php",
    body:    "username="+ this.username + "&password=" + this.password + "&clientid=" + config.clientid
    }, (error, response, body) => {
    this.emit("loggedIn", body)
    });
}

Then wait for the event after you call login()

let client = new Client(username, password)
client.on("loggedin", (returnVal) => console.log("returned", returnVal))
client.login()

Of course, you'll want some error checking, and you'll probably want to set a flag on your instance after logging in, so you can just check that after the initial login.

Upvotes: 1

3Dos
3Dos

Reputation: 3487

I think login() should return a promise :

login() {
  return new Promise((resolve, reject) => {
    http.post({
      url: config.host + "v" + config.version + "/method/account.signIn.inc.php",
      body: "username=" + this.username + "&password=" + this.password + "&clientid=" + config.clientid
    }, function(error, response, body) {
      if (error) reject(error);
      else resolve(body);
    });
  });
}

and when calling it :

client.login().then(result => console.log(result));

I'm kinda new to NodeJS and asynchronous programming but I think it's the way for doing this.

Upvotes: 0

Related Questions