0

After working with the helpful comments below, the solution settled in as follows:

async function grab_sysLvl_phase_program_mission() {
    const sysLvl = get("/api/SystemLevelList_url/").catch(err=>showErrorAlert(err));
    const phase = get("/api/mmSelectorPhase_url/").catch(err=>showErrorAlert(err));
    const program = get("/api/ProgramList_url/").catch(err=>showErrorAlert(err));
    const mission = get("/api/MissionList_url/").catch(err=>showErrorAlert(err));
    
    return await Promise.all([sysLvl,phase,program,mission])
}
//passed into .then(), takes the data from promise and formats it into an object
function createDataObject(obj){
    let data = {
        sysLvlList: obj[0],
        phaseList: obj[1],
        programList: obj[2],
        missionList: obj[3]
    }
    return data;
}
//stores the promise as constant
const defaultValues = grab_sysLvl_phase_program_mission();

//simple usage, can be called whenever the data is required without pinging the server again
defaultValues.then(obj => {
    const testing = createDataObject(obj);
    console.log(testing);
    console.log(testing.sysLvlList);
});

Thanks again for all the help.

Original Post Below -------------------

I have to make several calls to an API to get default data used throughout the site (the data is independent of each other, no key constraints). I am attempting to create a function that returns an object with all the returned data from the various calls. The API leverages a Django Restframework.

I was looking for data to be in this format:

defaultValues ={
   sysLvlList: {},
   phaseList: {},
   programList:{}
   missionList:{}
        }

Then be able to access the data through dot notation, defaultValues.sysLvlList etc. What I ended up doing was:

let defaultValues = {};
async function getSystemLevel_phase(){
    const sysLvl = get("/api/SystemLevelList_url/").then(r=>defaultValues.sysLvlList = r).catch(err=>showErrorAlert(err));
    const phase = get("/api/mmSelectorPhase_url/").then(r=>defaultValues.phaseList = r).catch(err=>showErrorAlert(err));
    const program = get("/api/ProgramList_url/").then(r=>defaultValues.programList = r).catch(err=>showErrorAlert(err));
    const mission = get("/api/MissionList_url/").then(r=>defaultValues.missionList = r).catch(err=>showErrorAlert(err));
    await Promise.all([sysLvl,phase,program,mission]);
}
getSystemLevel_phase();
console.log(defaultValues);
console.log(defaultValues.sysLvlList);

Which logged unidentified when attempting to use dot notation (see image below for reference). When working in the browser console, I would access the data. I believe the promise are fulfilling after the site renders.

What is printed to the console with console.log(defaultValues),console.log(defaultValues.sysLvlList)

Ideally, I would prefer to not have to define the variable outside of the function, but instead set the function to a variable like: const defaultValue = getSystemLevel_phase()

Any help would be appreciated, thank you

  • `await Promise.all(...)` is a point where your function gets suspended, and its caller continues immediately. `defaultValues` is still an empty object at that point. You just can't do this in top-level code. – tevemadar Jul 12 '22 at 17:22
  • You're not waiting for the requests to finish. Use `getSystemLevel_phase().then(() => { console.log(defaultValues); console.log(defaultValues.sysLvlList); })` or `await` – Bergi Jul 12 '22 at 17:30
  • "*I would prefer to not have to define the variable outside of the function*" - yes, good idea! Just declare it inside the function and `return` the value in the end. (And write `const defaultValue = await getSystemLevel_phase();` or `getSystemLevel_phase().then(defaultValue => {…})`) – Bergi Jul 12 '22 at 17:31
  • Thank you for the responses. I tried `return await Promise.all([sysLvl,phase,program,mission]);` then setting `const defaultValues = getSystemLevel_Phase().then(resp => data ={...})` and had the same problem when i tried to call the defaultValues from outside of .then(). It would not let me add await to the declaration line. – Terry Dunlap Jul 12 '22 at 17:57
  • @TerryDunlap That's the point, you *cannot* use the values outside of `then` (or without `await`) since that code outside of `then` runs before the values have been loaded. Move all the code that needs them inside the `then` callback. – Bergi Jul 12 '22 at 19:35
  • @Bergi is there a way to store the values as a global variable for the site to use, or will I need to repeat the fetch request each time I need the information? How did you intend this line: const defaultValue = await getSystemLevel_phase(); as I can only add await inside of an async function - wouldn't it have the same issue? – Terry Dunlap Jul 12 '22 at 20:43
  • @TerryDunlap You can store the promise itself in a global variable. But still, you will need to repeat the `.then()`/`await` code that does the waiting, since you'll always need to wait for the data. Better move all the (previously global) code inside the async function or `then` callback. – Bergi Jul 12 '22 at 21:12
  • @Bergi I appreciate all the help so far. Is there a way to limit the calls to the DB, would storing the promise.all to a global variable only ping the server the initial time? – Terry Dunlap Jul 12 '22 at 23:36
  • Yes, it would make the calls only when you call `getSystemLevel_Phase()`. You can afterwards attach any number of `.then()` callbacks to it – Bergi Jul 13 '22 at 00:09

0 Answers0