Cannot read property "responseText" of undefined

Viewed 525

I'm having an issue with my JSON.parse. After I change the API call from request to request.Promise.get I receive an error -

TypeError: Cannot read property 'responseText' of undefined

Packages:

Node-Schedule

Request-Promise

CoinMarketCap API

Is that a problem with my data in r1 or I don't understand at all what is wrong now with the code. I was trying to change responseText to responseXML doesn't work as well for me. Probably I'm missing the logic in the request but I'm just curious why this error appears even that this part of code was working before.

Problem area of code

const j = schedule.scheduleJob('* * * * * *', () => {
    requestPromise.get({
        uri: 'http://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?CMC_PRO_API_KEY=API-KEY-HERE',
        json: true
        resolveWithFullResponse: true
    }).then(r1 => {
        const x1 = JSON.parse(r1.target.responseText);

        const BTCdata = x1.data.find(d => d.symbol === 'BTC').quote.USD
            .volume_24h; // creating a variable to store a BTC request from API

        console.log(BTCdata);
        // Saving to database
        saveToDatabase(BTCdata);
    }).catch(err => {
        console.log(err);
    });
});

Full code

var requestPromise = require('request-promise');
const { MongoClient } = require('mongodb');
const schedule = require('node-schedule');
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;

const saveToDatabase = function(BTCdata) {
    const url = 'mongodb+srv://username:password@cluster0-1kunr.mongodb.net/<dbname>?retryWrites=true&w=majority';

    MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, (err, db) => {
        if (err) throw err;
        const dbo = db.db('Crypto');
        const myobj = { Name: 'BTC', Volume: 'BTCdata' };
        dbo.collection('Crypto-Values').insertOne(myobj, (error, res) => {
            if (error) throw error;
            console.log('1 document inserted');
            db.close();
        });
    });
};

function requestPromise(method, url) {
    return new Promise(((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.onload = resolve;
        xhr.onerror = reject;
        xhr.send();
    }));
}

const j = schedule.scheduleJob('* * * * * *', () => {
    requestPromise.get({
        uri: 'http://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?CMC_PRO_API_KEY=API-KEY-HERE',
        json: true
        resolveWithFullResponse: true
    }).then(r1 => {
        const x1 = JSON.parse(r1.target.responseText);

        const BTCdata = x1.data.find(d => d.symbol === 'BTC').quote.USD
            .volume_24h; // creating a variable to store a BTC request from API

        console.log(BTCdata);
        // Saving to database
        saveToDatabase(BTCdata);
    }).catch(err => {
        console.log(err);
    });
});
1 Answers

You have 2 mistakes here:

  1. In your requestPromise(), your response will be already JSON since you used json: true, so no need to additionally JSON.parse() it.

  2. In the very response itself (r1 in your case), you won't have target key. Instead, you should probably use r1.body to get the body of the response first and then do with the data from the body whatever you need.

const j = schedule.scheduleJob('* * * * * *', () => {
    requestPromise.get({
        uri: 'http://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?CMC_PRO_API_KEY=API-KEY-HERE',
        json: true,
        resolveWithFullResponse: true,
    }).then(r1 => {
        // r1.body will contain response from API
        const responseData = r1.body;

        // do something with responseData
    }).catch(err => {
        console.log(err);
    });
});

To get better idea what you will get in your r1.body object, refer to official documentation or simply put that API URL with proper key in your browser and you should see JSON output already.

Related