-2

I know promise is the answer for my issue but need help in how to use in my case.

my code is:

...

invoke: (abc) => {
    module.exports.getData();
    return;
},

getData: () => {
  request(options, function(err, res, body) {
    if (res && (res.statusCode === 200 || res.statusCode === 201)) {
      logger.info("vacation balacne response:" + body);
    }
  });
},

...

so in my current situation, the invoke method wont wait for getData to finish. I need to return response data from the call in getData and use it in the invoke method. Please advise.

Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153
Vik
  • 8,721
  • 27
  • 83
  • 168
  • You can't make `getData()` wait for the result (because of the way Javascript async operations work) and you can't return the result directly from `getData()` either because it's async and the function returns LONG before the async result is available. Instead, you can return a promise and then the caller can use the `.then()` method on the promise to retrieve the result when it is ready. The answer I've marked this a dup of shows you how to do that and there are hundreds of other articles on how to "promisify" something to make it return a promise. – jfriend00 Aug 12 '17 at 05:24
  • how do u do that? example plz – Vik Aug 12 '17 at 05:25
  • There a LONG treatise on how to do this in the [accepted answer for the question that yours is marked a duplicate of](https://stackoverflow.com/a/14220323/816620). Go read and study all of that. The link to that is right below your question title. The point of marking duplicates is to that we don't try to reproduce all that has been written before in yet another question on this topic. There are dozens of these types of questions posted every single day here as it's a new way of developing for most people that are new to node.js. It has to be learned. – jfriend00 Aug 12 '17 at 05:32

1 Answers1

0

Of course it won't, it's an asynchronous function. The simplest solution is to do move that callback from getData to invoke, so that invoke can pass it into getData, and getData can then called "whatever you need to have continue happening" once data is available:

var Thing = {
  ....

  invoke: (andThenDoThis) => {
    Thing.getData(andThenDoThis);
  },

  getData: (andThenDoThis) => {
    request(options, function(err, res, body) {
      if (res && (res.statusCode === 200 || res.statusCode === 201)) {
        logger.info("vacation balacne response:" + body);
      }

      // THIS IS WHERE YOUR CODE WILL NOW CONTINUE:
      if (andThenDoThis) {
        andThenDoThis(err, res, body)
      }
    });
  },
  ...
};

Although of course this is silly because just define an object with this referencing instead:

class Thing {
  constructor(options) { 
    this.options = options;
  }

  invoke() {
    this.getData((err, res, body) => {
      this.handleData(err, res, body);
    });
  }

  getData(andThenDoThis) {
    request(this.options, (err, res, body) => {
      this.handleData(err, res, body) 
    });
  }

  handleData(err, res, body) {
    // do some `err` checking
    // do some `res` checking
    // do some `body` parsing
    // do whatever else
    if (this.options.forwardData) {
      this.options.forwardData(...);
    } 
  }

  ...
} 

And then just make one of those things:

// make a thing:
let thing = new Thing({
  ...,
  forwardData: (data) => {
    // do whatever with your data.
  },
  ...
});

// and then invoke whatever it is you actually needed to do.
thing.invoke();

// code here keeps running, but that's fine, because now you're
// using "code triggers only when, and where, it needs to".
Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153