0

I can't resolve this question with the answers to this question because there are differences in the code.

I want to return an object out of a callback. When I run the below code, the log of the body object looks as expected. It appears to be the correct JSON object containing the response I want from the server: name, email, website, etc.

But the result object appears to contain information about the request itself instead of the response object.

How do I return the body object so that I can access it from the result variable?

const request = require('request'); // npm i request -s

module.exports = async config => {
  ...

  const result = await request.get( url, options,
    ( error, response, body, ) => {
      console.log( 'body', body, ); // I want the other log to look like this log.
      return body;
    }
  );

  console.log( 'result', result, ); // I want this log to look like the above log.
  // In other words, I want the below line to be the name, email, website JSON object
  // contained in the body
  return result;
}

This is what I want from result.

console.log( 'body', body, );
body {
  "name": "foo",
  "email": "foo@example.com",
  "website": "www.example.com",
  ...
}

This is what I actually get from result.

console.log( 'result', result, );
result Request {
  _events: [Object: null prototype] {
    error: [Function: bound ],
    complete: [Function: bound ],
    pipe: [Function]
  },
  _eventsCount: 3,
  _maxListeners: undefined,
  uri: Url {
    protocol: 'https:',
    slashes: true,
    auth: null,
    host: 'api.example.com',
    port: 443,
    hostname: 'api.example.com',
    hash: null,
  },
  callback: [Function],
  method: 'GET',
  readable: true,
  writable: true,
  explicitMethod: true,
  _qs: Querystring {
    request: [Circular],
    lib: { formats: [Object], parse: [Function], stringify: [Function] },
    useQuerystring: undefined,
    parseOptions: {},
    stringifyOptions: {}
  },
  _auth: Auth {
    request: [Circular],
trincot
  • 317,000
  • 35
  • 244
  • 286
Let Me Tink About It
  • 15,156
  • 21
  • 98
  • 207
  • 2
    `request.get()` does NOT return a promise, therefore `await` on it does nothing useful. If I had a nickel for every time I've responded to this question, I'd have a lot of nickels. `await` has no magic. All it does is wait on a promise. It doesn't do ANYTHING if you don't pass it a promise. – jfriend00 Jan 15 '20 at 21:18
  • https://www.npmjs.com/package/request#promises--asyncawait – str Jan 15 '20 at 21:19

2 Answers2

4

Use Promise:

const result = await new Promise((resolve) => {
  request.get(url, options, (error, response, body) => {
      console.log( 'body', body );
      resolve(body);
    });
});

Edit:

or you can install https://github.com/request/request-promise

KingGary
  • 628
  • 6
  • 16
  • 1
    FYI, the `request` module is in [maintenance mode](https://nodesource.com/blog/express-going-into-maintenance-mode) and will no longer get new features. Not really recommended to write new code with it. – jfriend00 Jan 15 '20 at 21:23
  • 1
    @jfriend00 Maintenance mode doesn't mean unsupported. It just means the dev doesn't feel anything else needs to be added. It's perfectly fine to use it in new code if it has everything you need. – Tarazed Jan 15 '20 at 21:26
  • @Tarazed - Well, it's dead-end code. If nodejs implements a new type of stream that is much more friendly to be used with promises, do you think the `request` module is going to support that new type of stream? I don't. It's getting bug fixes and that's it. If you're writing new code, much better to pick one of the actively being developed alternatives. Now, the world doesn't come to an end tomorrow if you use the `request()` library now, but I don't think it's the smartest choice for new code. It's also worth understanding why it's been put in maintenance mode. – jfriend00 Jan 15 '20 at 21:29
2

request.get() does NOT return a promise, therefore await on it does nothing useful. If I had a nickel for every time I've responded to this question, I'd have a lot of nickels. await has no magic. All it does is wait on a promise. It doesn't do ANYTHING if you don't pass it a promise.

You may not know, but the request module and its derivatives are in maintenance mode (no new features, only bug fixes). You can either use the request-promise module and then get rid of the callback or you can switch to a newer module that is being actively developed such as the got module. That would be my recommendation:

const got = require('got');

module.exports = async config => {
  ...

  const result = await got(url, options);

  console.log( 'result', result ); // I want this log to look like the above log.
  // In other words, I want the below line to be the name, email, website JSON object
  // contained in the body
  return result;
}

And, I hope you realize that ALL async functions return a promise so the caller of this function will have to either use await or .then() on the returned promise in order to get the result out of the promise.


If you wanted to stay with the request library, you can use request-promise to get an already promisified version of the library:

const rp = require('request-promise');

module.exports = async config => {
  ...

  const result = await rp(url, options);

  console.log( 'result', result ); // I want this log to look like the above log.
  // In other words, I want the below line to be the name, email, website JSON object
  // contained in the body
  return result;
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979