The reason it does this seems to be because the fetch_stockdata() function returns the value BEFORE the findOne() method and the code inside it is complete.
So the order I believe the program is running the code is:
Run fetch_stockdata()
Within fetch_stockdata() run fetch_price()
return stockdata_obj (which is undefined at the moment)
Within fetch_stockdata() run db_model.findOne() method
What I want the program to do instead is:
Run fetch_stockdata()
Within fetch_stockdata() run fetch_price()
Within fetch_stockdata() run db_model.findOne() method
return stockdata_obj (which is now not undefined as it has been filled by the db_model.findOne() method)
I have found a clean solution others may benefit from:
'use strict';
//Install and set up mongodb and mongoose
const mongodb = require('mongodb');
const mongoose = require('mongoose');
const mySecret = process.env['MONGO_URI']
const Jfuncs = require('../controllers/Jfuncs.js');
module.exports = function (app) {
// This variable creates an instance of the class Jfuncs (i.e. creates an object) when called
let jfunc = new Jfuncs();
//Connect mongoose to mongodb database
mongoose.connect(mySecret, { useNewUrlParser: true, useUnifiedTopology: true });
//Create a schema and a Model for data going into mongodb database
const { Schema } = mongoose;
const stockSchema = new Schema({
stock_symbol: {type: String, required: true},
ips_that_like_it: {type: [String], required: true},
likes_for_that_stock: {type: Number, required: true}
});
const Stock = mongoose.model('Stock', stockSchema);
// What must happen when we click the first 'Get Price!' button
app.route('/api/stock-prices')
.get(async function (req, res){
if (typeof req.query.stock == 'string') {
// 1 stock - Get single price and total likes
let stockFound_1 = await Stock.findOne({ stock_symbol: req.query.stock }).exec();
console.log(stockFound_1);
let stockdata_obj = jfunc.fetch_stockdata(
req.query.stock,
req.query.like,
req.ip,
stockFound_1
);
return res.json(stockdata_obj);
} else if(typeof req.query.stock == 'object' /* In JS, an array is type object*/) {
// 2 stocks - Compare and get relative likes
// Get first stock object
let stockFound_1 = await Stock.findOne({ stock_symbol: req.query.stock[0] }).exec();
let stockdata_obj_1 = jfunc.fetch_stockdata(
req.query.stock[0],
req.query.like,
req.ip,
stockFound_1
);
console.log(stockdata_obj_1);
// Get second stock object
let stockFound_2 = await Stock.findOne({ stock_symbol: req.query.stock[1] }).exec();
let stockdata_obj_2 = jfunc.fetch_stockdata(
req.query.stock[1],
req.query.like,
req.ip,
stockFound_2
);
console.log(stockdata_obj_2);
// Join the two in a single object to show user relative likes
let stockdata_objs_compared = jfunc.stockdata_comparison_obj_creator(stockdata_obj_1,stockdata_obj_2);
return res.json(stockdata_objs_compared);
}; // closes 'else if'
}); // closes '.get route'
}; // closes 'module.exports'
The keys to the solution are: using ‘async’ and ‘await’, and retrieving records from mongoDB using the following simple line of code, instead of complicated callback functions:
let stockFound_1 = await Stock.findOne({ stock_symbol: req.query.stock }).exec();