0

My code:

var price = {};
function getPrice(price) {
    const https = require('https');
    var item = ('M4A1-S | Decimator (Field-Tested)')
    var body = '';
    var price = {};
    https.get('https://steamcommunity.com/market/priceoverview/?appid=730&market_hash_name=' + item, res => {
        res.on('data', data => {
            body += data;
        })
        res.on('end', () => price ['value'] = parseFloat(JSON.parse(body).median_price.substr(1))); //doesnt add to dict
    }).on('error', error => console.error(error.message));
}
price['test'] = "123" //adds to dict fine
getPrice(price)
console.log(price);

Output:

{ test: '123' }

as you can see, the "test: 123" gets added, but the "value: xxx" from the function doesn't. Why is that?

jogge
  • 15
  • 2
  • The value is set in an asynchronous callback AFTER you `console.log()` the value since your `getPrice()` function returns long before you set the value. So, you're logging too soon. See [How do I return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call/14220323#14220323) for details. You are also redeclaring a separate `price` variable inside the function that has nothing to do with the higher scoped price variable so even if you didn't have the asynchronous issue, you'd be modifying the wrong variable. – jfriend00 Jul 19 '20 at 15:40
  • Also, I'd suggest you use something higher level than `https.get()` that supports promises and automatically fetches the whole response for you and handles errors appropriately. There is a list of good libraries here: https://github.com/request/request/issues/3143. – jfriend00 Jul 19 '20 at 15:43
  • Does this answer your question? [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Dan O Jul 19 '20 at 15:52
  • @DanO - That's only part of the issue. They are also redeclaring the variable inside the callback which also needs to be fixed. – jfriend00 Jul 19 '20 at 15:53

3 Answers3

0

You're actually console.logging .price before you're setting .value; .value isn't set until the asynchronous call fires.

ralphmerridew
  • 324
  • 1
  • 3
  • But i call the function first, and console.log after (last two lines). How would I fix this? – jogge Jul 19 '20 at 15:30
0

You are declaring price again inside the function and also not waiting for the asynchronous task to finish.

const https = require("https");
const getPrice = () =>
    new Promise((resolve, reject) => {
        const item = "M4A1-S | Decimator (Field-Tested)";
        let body = "";
        return https
            .get(
                `https://steamcommunity.com/market/priceoverview/?appid=730&market_hash_name=${item}`,
                res => {
                    res.on("data", data => {
                        body += data;
                    });
                    res.on("end", () =>
                        resolve(
                            parseFloat(JSON.parse(body).median_price.substr(1))
                        )
                    );
                }
            )
            .on("error", error => reject(error));
    });

const main = async () => {
    try{
        const price = await getPrice();
        //use the price value to do something
    }catch(error){
        console.error(error);
    }
};
main();
Darvesh
  • 645
  • 7
  • 15
0

There are two main problems here:

  1. You're redeclaring the variable inside your function so you're declaring a separate, new variable and modifying that so the higher scoped variable, never gets your .value property.

  2. You're assigning the property inside an asynchronous callback that runs sometime later after your function has returned and thus your function actually returns and you do the console.log() too soon before you have even obtained the value. This is a classic issue with return asynchronously obtained data from a function in Javascript. You will need to communicate back that data with a callback or with a promise.

I would also suggest that you use a higher level library that supports promises for getting your http request and parsing the results. There are many that already support promises, already read the whole response, already offer JSON parsing built-in, do appropriate error detection and propagation, etc... You don't need to write all that yourself. My favorite library for this is got(), but you can see a list of many good choices here. I would strongly advise that you use promises to communicate back your asynchronous result.

My suggestion for fixing this would be this code:

const got = require('got');

async function getPrice() {
    const item = 'M4A1-S | Decimator (Field-Tested)';
    const url = 'https://steamcommunity.com/market/priceoverview/?appid=730&market_hash_name=' + item;
    const body = await got(url).json();
    if (!body.success || !body.median_price) {
        throw new Error('Could not obtain price');
    }
    return parseFloat(body.median_price.substr(1));
}

getPrice().then(value => {
    // use value here
    console.log(value);
}).catch(err => {
    console.log(err);
});

When I run this, it logs 5.2.

jfriend00
  • 683,504
  • 96
  • 985
  • 979