Skip to content

Commit

Permalink
Return promises in one loop instead of in nested lopo.
Browse files Browse the repository at this point in the history
  • Loading branch information
lublagg committed Sep 21, 2023
1 parent 5a6988d commit 7ae7163
Showing 1 changed file with 63 additions and 76 deletions.
139 changes: 63 additions & 76 deletions src/scripts/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ interface IRequestParams {
state?: string
}

interface IGetAttrDataParams {
attribute: string,
interface IGetItemParams {
requestString: string,
countyOrState: string,
geographicLevel: string,
cropUnits: string,
location: string,
year: string
state?: string
}

export const fetchDataWithRetry = async (req: string, maxRetries = 3) => {
Expand Down Expand Up @@ -134,7 +132,14 @@ export const createTableFromSelections = async (selectedOptions: IStateOptions)
const {geographicLevel, states, cropUnits, years, ...subOptions} = selectedOptions;
try {
const allAttrs = getAllAttrs(selectedOptions);
const items = await getItems(selectedOptions);
const requests = getAllRequests(selectedOptions);
const promises = [];
for (const req of requests) {
const {requestString, year, countyOrState} = req;
const res = getItem({requestString, year, countyOrState, geographicLevel: req.geographicLevel});
promises.push(res);
}
const items = await Promise.all(promises);
await connect.getNewDataContext();
await connect.createTopCollection(geographicLevel);
await connect.createSubCollection(geographicLevel, allAttrs);
Expand All @@ -148,97 +153,79 @@ export const createTableFromSelections = async (selectedOptions: IStateOptions)
}
};

const getItems = async (selectedOptions: IStateOptions) => {
const getAllRequests = (selectedOptions: IStateOptions) => {
let {states, years} = selectedOptions;
const multipleStatesSelected = states.length > 1 || states[0] === "All States";
const multipleYearsSelected = years.length > 1;
const countySelected = selectedOptions.geographicLevel === "County";

if (states[0] === "All States") {
states = fiftyStates;
}

const promises = [];

if (multipleStatesSelected) {
for (const state of states) {
if (multipleYearsSelected) {
for (const year of years) {
if (countySelected) {
const allCounties = countyData[state];
for (const county of allCounties) {
const item = getDataForSingleYearAndState(selectedOptions, county, year, state);
promises.push(item);
}
} else {
const item = getDataForSingleYearAndState(selectedOptions, state, year);
promises.push(item);
}
const requests = [];

for (const state of states) {
const locations = countySelected ? countyData[state] : [state];
for (const year of years) {
for (const location of locations) {
const req = getRequest(selectedOptions, location, year, state);
if (req) {
requests.push(req);
}
} else {
const item = getDataForSingleYearAndState(selectedOptions, state, years[0]);
promises.push(item);
}
}
} else {
if (countySelected) {
const allCounties = countyData[states[0]];
for (const county of allCounties) {
const item = getDataForSingleYearAndState(selectedOptions, county, years[0], states[0]);
promises.push(item);
}
} else {
const item = getDataForSingleYearAndState(selectedOptions, states[0], years[0]);
promises.push(item);
}
}
return await Promise.all(promises);
};

const getDataForSingleYearAndState = async (selectedOptions: IStateOptions, countyOrState: string, year: string, state?: string) => {
const {geographicLevel, states, years, cropUnits, ...subOptions} = selectedOptions;
return requests;
};

let item: any = {
[geographicLevel]: countyOrState,
"Year": year,
};
const getItem = async ({requestString, countyOrState, geographicLevel, year}: IGetItemParams) => {
const attrData = await getAttrData(requestString);
if (Object.keys(attrData).length) {
return {
[geographicLevel]: countyOrState,
"Year": year,
...attrData
};
}
};

const getRequest = (selectedOptions: IStateOptions, countyOrState: string, year: string, state?: string) => {
const {geographicLevel, states, years, cropUnits, ...subOptions} = selectedOptions;
for (const key in subOptions) {
const value = subOptions[key as keyof typeof subOptions];
if (value && Array.isArray(value)) {
for (const attribute of value) {
const queryParams = getQueryParams(attribute);
const yearAvailable = queryParams?.years[geographicLevel].includes(year);
const isMultiStateRegion = queryParams?.geographicAreas[0] === "REGION : MULTI-STATE";
const geoLevel = isMultiStateRegion ? "REGION : MULTI-STATE" : geographicLevel;
if (yearAvailable) {
let location = countyOrState;
if (isMultiStateRegion) {
const itemToCheck = state ? state : countyOrState;
const regData = multiRegions.find((region) => region.States.includes(itemToCheck));
location = regData?.Region ? regData.Region : countyOrState;
}
const params: IGetAttrDataParams = {attribute, geographicLevel: geoLevel, location, year, cropUnits};
if (geoLevel === "County") {
params.state = state;
}
const attrData = await getAttrData(params);
item = {...item, ...attrData};
for (const attribute of value) {
const queryParams = getQueryParams(attribute);
const yearAvailable = queryParams?.years[geographicLevel].includes(year);
const isMultiStateRegion = queryParams?.geographicAreas[0] === "REGION : MULTI-STATE";
const geoLevel = isMultiStateRegion ? "REGION : MULTI-STATE" : geographicLevel;
if (yearAvailable) {
let location = countyOrState;
if (isMultiStateRegion) {
const itemToCheck = state ? state : countyOrState;
const regData = multiRegions.find((region) => region.States.includes(itemToCheck));
location = regData?.Region ? regData.Region : countyOrState;
}
const params: IRequestParams = {attribute, geographicLevel: geoLevel, location, year};
if (geoLevel === "County") {
params.state = state;
}
if (cropOptions.options.includes(attribute) && cropUnits) {
params.cropCategory = cropUnits as keyof ICropDataItem;
}
return {
requestString: createRequest(params),
countyOrState,
geographicLevel,
year
};
}
}
}

return item;
}
};

const getAttrData = async (params: IGetAttrDataParams) => {
const {attribute, geographicLevel, location, year, cropUnits, state} = params;
const reqParams: IRequestParams = {attribute, geographicLevel, location, year, state};
if (cropOptions.options.includes(attribute) && cropUnits) {
reqParams.cropCategory = cropUnits as keyof ICropDataItem;
}
const req = createRequest(reqParams);

const getAttrData = async (req: string) => {
const res = await fetchDataWithRetry(req);
const values: any = {};
if (res) {
Expand All @@ -249,7 +236,7 @@ const getAttrData = async (params: IGetAttrDataParams) => {
});
} else {
// eslint-disable-next-line no-console
console.log(`Error: did not receive response for item with these params: ${params}`);
console.log(`Error: did not receive response for this request:`, req);
}
return values;
};

0 comments on commit 7ae7163

Please sign in to comment.