0

I'm running my javascript code with node.js and am using the request-promise library to generate https requests which return a json blob. So far, I've managed to send the request correctly--and I do receive the desired json object in the response, but I'm only seeing the keys, not the values. I want to extract the value for a key called "call_count". The problem I'm facing is the peculiar structure of the request-promise syntax, which appears to be preventing me from doing what I want to do.

Here's what the JSON response looks like when I run my query in Postman:

{
  "metric_data": {
    "from": "2021-12-12T23:56:12+00:00",
    "to": "2021-12-13T00:26:12+00:00",
    "metrics_not_found": [],
    "metrics_found": [
        "Mobile/Crash/All"
    ],
    "metrics": [
        {
            "name": "Mobile/Crash/All",
            "timeslices": [
                {
                    "from": "2021-12-12T23:53:00+00:00",
                    "to": "2021-12-13T00:23:00+00:00",
                    "values": {
                        "call_count": 0
                    }
                }
            ]
        }
    ]
  }
}

And here's my code that generates the request:

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

let options = {
  method: 'GET',
  uri: 'https://api.crashCatcher.com/v2/mobile_applications/myAppID/metrics/data.json?names=Mobile/Crash/All&values[]=call_count&summarize=true',
  headers: {
    'User-Agent': 'request-promise',
    'X-Api-Key': 'MY API key goes here'
  },
  json: true // Automatically parses the JSON string in the response
};

rp(options).then(body => console.log(body)).catch(err => console.log(err.name, err.statusCode));

Currently, when I run this code, here's what I'm getting back:

{ metric_data: 
   { from: '2021-12-13T00:22:04+00:00',
     to: '2021-12-13T00:52:04+00:00',
     metrics_not_found: [],
     metrics_found: [ 'Mobile/Crash/All' ],
     metrics: [ [Object] ] } }

Now, I know I'm getting a JSON object back, and I know I need to do something like:

var myJson = JSON.parse(*body*);

And then something like:

console.log(myJson.metric_data.metrics[0].timeslices[0].values.call_count);

But when using the request-promise syntax, I don't know how to correctly assign what's coming back in my response body to a variable that I can then JSON.parse and extract the needed call_count value from.

Inigo
  • 12,186
  • 5
  • 41
  • 70
Wulf
  • 379
  • 1
  • 6
  • 16
  • "*I don't know how to correctly assign what's coming back in my response body to a variable*" - the parameter `body` of the function `body => console.log(body)` already *is* that variable. – Bergi Dec 13 '21 at 01:58
  • "*I know I'm getting a JSON object back, and I know I need to do something like `JSON.parse(body)`*" - no you don't! You even wrote it in the code yourself: `json: true // Automatically parses the JSON string in the response`. With that option, the `request` library does the parsing, and fulfills the promise with the parsed object, not the JSON text. – Bergi Dec 13 '21 at 01:59
  • @Bergi, you're right. But I think the asker's problem is how to perform complex logic in the `then` clause. Bergi, if I't wrong, please revert my edit of your question and be more specific about what your problem is. – Inigo Dec 13 '21 at 02:09
  • The console log output of `[Object]` suggests to me the logging code is not expanding all nested levels of an object it's been asked to log - which is what node's `console.log` does when logging complex objects. Have you tried `rp(options).then( dataObj => ..process data.. )` to see if it's working already? – traktor Dec 13 '21 at 02:20
  • Please realize that the `request()` library has been [deprecated](https://github.com/request/request#deprecated) and it is not recommended to be writing lots of new code with it. Instead, there is a list of very capable alternatives that all support promises natively [here](https://github.com/request/request/issues/3143). My personal favorite is [got()](https://www.npmjs.com/package/got) because I like its interface and it supports most of the options of the request() library, but you can review the list and decide which one you like most. – jfriend00 Dec 13 '21 at 03:14
  • Also, the `request()` library or any of the above replacements can all do the JSON parsing for you - you don't have to do that manually. – jfriend00 Dec 13 '21 at 03:27

2 Answers2

1

You aren't limited to using arrow functions, and even arrow functions can have full function bodies.

For example:

rp(options).then(
    body => {
        let myJson = JSON.parse(body);
        console.log(myJson.metric_data.metrics[0].timeslices[0].values.call_count);
    }
).catch(err => console.log(err.name, err.statusCode));

or:

rp(options).then(
    function (body) {
        let myJson = JSON.parse(body)
        console.log(myJson.metric_data.metrics[0].timeslices[0].values.call_count)
    }
).catch(err => console.log(err.name, err.statusCode));

or even:

function handleResponse (body) {
    let myJson = JSON.parse(body)
    console.log(myJson.metric_data.metrics[0].timeslices[0].values.call_count)
}

rp(options).then(handleResponse).catch(err => console.log(err.name, err.statusCode));

or even:

const handleResponse = body => {
    let myJson = JSON.parse(body);
    console.log(myJson.metric_data.metrics[0].timeslices[0].values.call_count);
}

rp(options).then(handleResponse).catch(err => console.log(err.name, err.statusCode));

Inigo
  • 12,186
  • 5
  • 41
  • 70
  • Yes, except the OP actually *shouldn't* call `JSON.parse` – Bergi Dec 13 '21 at 02:01
  • Yeah but that's not the OP's question. He even said "something like". We should be answering the actual specific question, just as we ask for questions to be specific and focused on a single problem. – Inigo Dec 13 '21 at 02:05
  • Thank you very much for these examples! I am most appreciative and grateful for the time taken to write these up for me and I am learning! Thank you! I must be doing something wrong, however, because each example, when run from the cli in VS Code, triggers the following error response: SyntaxError undefined – Wulf Dec 13 '21 at 04:04
  • I checked for errors before running each example and did my best to clear things up and eliminate any indication of a syntax issue, but no joy. The example below looks best to me. Do you see any syntax errors in this example? rp(options).then( body => { let myJson = JSON.parse(body); console.log(myJson.metric_data.metrics[0].timeslices[0].values.call_count); } ).catch(err => console.log(err.name, err.statusCode)); – Wulf Dec 13 '21 at 04:05
  • @Wulf NONE of my examples have real syntax errors. The undefined errors are not really syntax errors. These are code snippets (based on what you gave in your question) that won't compile with the variables they refer too. That's your job, because we don't have the rest of your code. My answer addresses just your one question about how to have more logic in the `then` clause. – Inigo Dec 13 '21 at 05:10
  • Understood. Thanks very much for the help given! Thank you! – Wulf Dec 13 '21 at 05:19
  • np. if it was helpful, i wouldn't mind the upvote. And an answer accept, unless you are looking for something more and are holding out hope someone else will come in with some magic ;) – Inigo Dec 13 '21 at 05:30
  • 1
    @inigo I'll definitely give you an up vote! I do have internal resources that I've just reached out to--as I've wasted the weekend trying to get this working and have formally surrendered. I'm hoping to get a resolution tomorrow morning and then will come back here and update with the corrections needed and will do all the upvoting and solution marking then! Thanks again! I've learned a lot! Most importantly, that I don't like javascript! Hah! – Wulf Dec 13 '21 at 05:50
1

So, the solution was to remove the json: true setting in my options. Once that was done, all solutions kindly listed by Inigo, worked! Thanks again for the help! This was a huge learning experience.

let options = {
  method: 'GET',
  uri: 'https://api.crashCatcher.com/v2/mobile_applications/960867101/metrics/data.json?names=Mobile/Crash/All&values[]=call_count&summarize=true',
  headers: {
    'User-Agent': 'request-promise',
    'X-Api-Key': 'My API key'
  }
};
Wulf
  • 379
  • 1
  • 6
  • 16