Stock Price Checker - Possible Error Due to API Performance?

I’ve completed the Stock Price Checker project from the Information Security and Quality Assurance certification to the point where all of the functional tests pass intermittently. I emphasize intermittently because when I’m attempting to retrieve stock data from the API and assign it to the res.locals object to pass through my route handler, the application will sometimes error out with an error along the lines of “Cannot read property of ‘01. symbol’ of undefined”. I should be clear that I know the application works and the logic is sound, because like I said, it will pass the tests the majority of the time.

I cannot figure out a fix to prevent this from happening 100% of the time. I’m currently using Promises combined with async/ await functionality, but that isn’t doing the trick completely. I also tried adding a package in to limit the rate at which requests could be submitted to retrieve data from the API, but that also didn’t fix the issue.

I am using an API from Alphavantage (https://www.alphavantage.co/documentation/) to obtain the stock data, since the Google API indicated in the instructions no longer exists. I would like some help figuring out how to prevent this error from happening 100% of the time. I have a feeling that the root cause may lie with the performance available from Alphavantage (given it is a free service), however, I should be able to some sort of delay into my code to circumvent the issue if that is the case.

My Github Repo for this project is here: https://github.com/bloo0178/ISP4

The Glitch page is here; however, I find it’s easier to troubleshoot if you instead download and run the code from my Github Repo - particularly because Glitch will just crash and the reload process doesn’t always do the trick. https://glitch.com/edit/#!/isp4

The code in question is below (I believe, unless you go to my GitHub repo to dig through the entire codebase). The first function (getApiData) is used by the second function (initializeStockObjects). InitializeStockObjects is passed as a handler on the GET route for ‘/api/stock-prices’.

You can see in the second function that if a query exists for the second stock that the API call is made twice - once for each stock. This is where the application sometimes gets hung up - returning the error I described above (“Cannot read property of ‘01. symbol’ of undefined").

EDIT: Another question - I was under the impression that res.locals was the preferred way to past variable data between Express middleware. Are there better alternatives?

let getApiData = (stock) => {
        let URL = 'https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol='
            + stock + '&apikey=' + process.env.ALPHA_API_KEY;
        let stockObj = {};
        return new Promise((resolve, reject) => {
            request(URL, { json: true }, (err, res, body) => {
                if (err) { return console.log(err) };
                stockObj.stock = body['Global Quote']['01. symbol'];
                stockObj.price = body['Global Quote']['05. price'];
                resolve(stockObj);
            })
        })
    }

    let initializeStockObjects = async (req, res, next) => {
        res.locals.obj1 = {};
        res.locals.obj2 = {};
        try {
            res.locals.obj1 = await getApiData(req.query.stock1);
        } catch (err) {
            console.log(err);
        }
        if (req.query.stock2) {
            console.log('two stocks - first stock is: ' + req.query.stock1);
            console.log("two stocks - second stock is: " + req.query.stock2);
            try {
                res.locals.obj2 = await getApiData(req.query.stock2);
            } catch (err) {
                console.log(err);
            }
        }
        next();
    }

Did some more testing and logging and found that when I would get the aforementioned error, if I also logged the Request body as well I got the following: “{ Information: ‘Thank you for using Alpha Vantage! Please visit https://www.alphavantage.co/premium/ if you would like to have a higher API call volume.’ }
TypeError: Cannot read property ‘01. symbol’ of undefined”

I assume that means there is no workaround because the API is not as performant for non-premium users? Is there no way to hold the “await” until the Request body is actually returning the expected data format?

Went to their site, and sure enough, the limit is 5 calls per minute. This would explain why my automated testing was failing the final tests when run all at once (versus individually). Across all tests I was exceeding the 5 calls per minute threshold which changed the Response body to be the “Information: …” text above.

In certain high-frequency use cases that exceed our standard call-frequency limit (5 requests per minute), we offer a dedicated, premium API key which allows various tiers of API calls per minute.

Marking this as closed now.

2 Likes

I had the same problem. Thank you for posting @bloo0178

1 Like

I used the same API and have been racking my brain trying to figure out what’s wrong- refactored and refactored and refactored… LOL

Thank you for tracking this one down.

1 Like

I ran into this and decided to “cache” results in mongo with a timestamp ($currentDate) to then only re-query the alphavantage API when my data was older than 60s.

I figured it was something worth doing as something like this could happen in the real world even with a premium API key (timeouts etc).

Cool! Can you please share your implementation?

It might be a little tricky to follow, but it’s all here: https://github.com/jbalke/FCC-Stock-Price-Checker/blob/master/controllers/stockHandler.js

I’ve been running into this issue as well but in fact, even within the free tier rate, the requests fail with a 200. The response comes back with an error stating the query is invalid despite it being valid.

I didn’t build this using node but out of a C# console app. It’s possible that AlphaVantage cannot handle the load is bearing from all the free tier requests