In JS, modify function in more university - javascript

I have a function for fetch data. But how can made this function more universal? For example, else quantity of arguments would be change.
var url = [
'http://www.json-generator.com/api/json/get/cevhxOsZnS',
'http://www.json-generator.com/api/json/get/cguaPsRxAi',
'http://www.json-generator.com/api/json/get/cfDZdmxnDm'
]
fetchData(...url)
function fetchData(a, b, c) {
var arr = [];
fetch(a)
.then(res => res.json())
.then(res => {
arr.push(res)
return fetch(b)
})
.then(res => res.json())
.then(res => {
arr.push(res)
return fetch(c)
})
.then(res => res.json())
.then(res => arr.push(res))
.then(res => console.log(arr))
}

From looking at your code, I am assuming that fetch is a function that takes an URL as input and returns a Promise.
You can make use of the fact that the arguments keyword in javascript contains all the arguments with which the function was called and make a recursive function to do what you want.
Example code for that would be like this:
var url = [
'http://www.json-generator.com/api/json/get/cevhxOsZnS',
'http://www.json-generator.com/api/json/get/cguaPsRxAi',
'http://www.json-generator.com/api/json/get/cfDZdmxnDm'
]
fetchData(...url)
function fetchData() {
var arr = [];
fetchRecursive(arguments, arr);
}
function fetchRecursive (args, arr, i = 0) {
if (i < args.length - 1) {
return fetch(args[i])
.then(res => res.json())
.then(res => {
arr.push(res);
return fetchRecursive(args[++i]);
});
} else {
return fetch(args[i])
.then(res => res.json())
.then(res => {
arr.push(res);
console.log(arr);
});
}
}

Here's another solution with a generator and async / await.
var url = [
'http://www.json-generator.com/api/json/get/cevhxOsZnS',
'http://www.json-generator.com/api/json/get/cguaPsRxAi',
'http://www.json-generator.com/api/json/get/cfDZdmxnDm'
];
function* fetchData(urls) {
var result = [];
for (someUrl of urls) {
console.log("Fetching ", someUrl);
yield new Promise((resolve) => {
fetch(someUrl).then(res => {
res.json().then(res => {
result.push(res);
resolve();
});
})
});
}
return result;
}
async function asyncCall() {
var iterator, iteration;
iterator = fetchData(url);
do {
iteration = iterator.next();
await iteration.value;
} while (!iteration.done);
console.log("done ", iteration.value);
}
asyncCall();

Related

function not return value from request

I made a function to get request. It look like this
export const toggleCompleted = (id) => {
axiosMethod.get('api/taks/toggle/' + id)
.then(res => {
console.log(res.data)
return res.data;
}).catch(error => {
return error;
})
return 'Test';
}
I want to get this request and if PHP return true, run dispatch. So I made this code
const markAsCompleted = (id) => {
console.log(toggleCompleted(id));
if (toggleCompleted(id) == 1){
toggleMarkAsCompleted(id);
}
}
toggleCompleted is a my request which is show before
toggleMarkAsCompletedis my dispatch.
If toggleCompleted return 1 I want to run my dispatch. It's simple? Interested is that this code
console.log(toggleCompleted(id));
return Test while my request 1 or 0 (from .then()). Why?
Add return in the toggleCompleted and use async/await to get return data
export const toggleCompleted = (id) => {
return axiosMethod
.get("api/taks/toggle/" + id)
.then((res) => {
console.log(res.data);
return res.data;
})
.catch((error) => {
return error;
});
};
const markAsCompleted = async (id) => {
const res = await toggleCompleted(id);
if (res == 1) {
toggleMarkAsCompleted(id);
}
};

update two remote api and retry multiple time

My goal is to fetch data from two remote api and update the data from the two api simultaneously. If the first api update pass and the second api update fails, all update should be reverse. I am having issue in making sure all data is fetch and update at the same time. Please see my current code below. I am working in node.js environment. Thanks.
const remote1 = 'https://jsonplaceholder.typicode.com/posts/1'
const remote2 = 'https://jsonplaceholder.typicode.com/posts/2'
var data1;
var data2;
fetch(remote1)
.then(res => res.json())
.then(data => data1 = data)
fetch(remote1)
.then(res => res.json())
.then(data => data2 = data)
const trys= 3;
function updateApi() {
return new Promise((ok, fail) => {
setTimeout(() => data1.id = 2, data2.id = 3 ? ok("OK!") : fail("Error"), 6000);
});
}
async function Retry(updateApi, count = trys) {
if (count > 0) {
const result = await updateApi().catch(e => e);
if (result === "Error" ) {
return await Retry(updateApi, count - 1) }
return result
}
return `Tried ${trys} times and failed`;
}
Retry(updateApi).then(console.log);
Don't use promise as like callback, Promise is just future value,
const remote1 = 'https://jsonplaceholder.typicode.com/posts/1'
const remote2 = 'https://jsonplaceholder.typicode.com/posts/2'
var data1 = fetch(remote1)
.then(res => res.json())
.then(data => data1 = data)
var data2 = fetch(remote1)
.then(res => res.json())
.then(data => data2 = data)
function updateApi() {
// waiting for both `data1` and `data2` to resolve...
return Promise.all([data1, data2]).then(_ => {
data1.id = 2;
data2.id = 3;
})
}
async function Retry(updateApi, count = 3) {
if (!count) throw `Tried ${count} times and failed`
try {
await updateApi();
} catch (error) {
await Retry(updateApi, count - 1)
}
}
Retry(updateApi)
.then(() => console.log({ data1, data2 }))
.catch(console.log);

I am facing problem chaining the async code in Javascript

I am trying to execute allCountryData and return a promise its working fine but after allCountryData is done executing I want to perform a operation on that returned data / or allCountryDataArray and store the highest values in arrayOfHighestCases
Note I can't chain the other login in allCountryData.
Please help let me know if you need any more details
export const allCountryDataArray = [];
export const arrayOfHighestCases = [];
const allCountryData = async () => {
sendHTTP()
.then((res) => {
return res.response;
})
.then((res) => {
allCountryDataArray.push(...res);
return allCountryDataArray;
});
return await allCountryDataArray;
// Highest Cases
};
The code is below is not working
const highestCasesData = async () => {
// const allCountryDataArrayy = await allCountryData();
// allCountryData()
// .then((data) => {
// console.log(arrayOfHighestCases[0]);
// })
// .then((res) => {
const np = new Promise((res, rej) => {
res(allCountryData());
});
return np.then((res) => {
console.log(res);
const arrayofHigh = allCountryDataArray.sort((a, b) => {
if (a.cases.total < b.cases.total) {
return 1;
} else if (a.cases.total > b.cases.total) {
return -1;
} else {
return 0;
}
});
console.log(arrayofHigh);
const slicedArray = arrayofHigh.slice(0, 6);
for (const eachHighCase of slicedArray) {
arrayOfHighestCases.push(eachHighCase);
}
console.log(arrayOfHighestCases);
return arrayOfHighestCases;
});
// });
};
highestCasesData();
Filling global arrays with async data is a way into timing conflicts. Bugs where the data ain't there, except when you look it is there and yet another question here on my SO about "Why can't my code access data? When I check in the console everything looks fine, but my code ain't working."
If you want to store something, store Promises of these arrays or memoize the functions.
const allCountryData = async () => {
const res = await sendHTTP();
return res.response;
};
const highestCasesData = async () => {
const allCountryDataArray = await allCountryData();
return allCountryDataArray
.slice() // make a copy, don't mutate the original array
.sort((a, b) => b.cases.total - a.cases.total) // sort it by total cases DESC
.slice(0, 6); // take the first 6 items with the highest total cases
}
This is working please let me know if I can make some more improvements
const allCountryData = async () => {
return sendHTTP()
.then((res) => {
return res.response;
})
.then((res) => {
allCountryDataArray.push(...res);
return allCountryDataArray;
});
// Highest Cases
};
const highestCasesData = async () => {
return allCountryData().then((res) => {
console.log(res);
const arrayofHigh = allCountryDataArray.sort((a, b) => {
if (a.cases.total < b.cases.total) {
return 1;
} else if (a.cases.total > b.cases.total) {
return -1;
} else {
return 0;
}
});
console.log(arrayofHigh);
const slicedArray = arrayofHigh.slice(0, 6);
for (const eachHighCase of slicedArray) {
arrayOfHighestCases.push(eachHighCase);
}
console.log(arrayOfHighestCases);
return arrayOfHighestCases;
});
};
highestCasesData();

Cannot access object/array in Javascript

I can console.log and see the array I created but as soon as I attempt to access it, I get undefined.
async componentDidMount() {
// fetch goal data for display
let response = await fetchWithToken("http://localhost:8080/api/getGoals");
let goalData = await response.json();
goalData = await goalData.filter(skill => skill.Skill === "CS_en");
// get info from people API with distinct list rather than every row
let people = new Set([]);
goalData
.filter(element => element.UpdatedBy !== null)
.forEach(element => {
people.add(element.UpdatedBy);
});
people = Array.from(people);
// call peopleAPI
const peopleObj = await peopleAPI(people);
console.log("peopleObj :", peopleObj);
console.log("peopleObj[0] :", peopleObj[0]);
}
Here is the peopleAPI where I'm calling another api and getting a list of user info.
const peopleAPI = people => {
return new Promise(function(resolve, reject) {
// get people API info
const peopleObj = [];
const apiPromises = [];
if (people) {
people.forEach(empid => {
const apiPromise = fetch(
`https://someApiCall/${empid}`
)
.then(res => res.json())
.then(res => {
peopleObj.push({
empid: res.id,
name: res.name.preferred ? res.name.preferred : res.name.full
});
})
.then(() => apiPromises.push(apiPromise));
});
// once all promises have been resolved, return a promise with the peopleObj
Promise.all(apiPromises).then(() => {
resolve(peopleObj);
});
}
});
};
export default peopleAPI;
Results of console.logs
Don't use push inside fetch.then, just return its value, and then push it to apiPromises`
const peopleAPI = people => {`
return new Promise(function(resolve, reject) {
// get people API info
const apiPromises = [];
if (people) {
people.forEach(empid => {
const apiPromise = fetch(`https://someApiCall/${empid}`)
.then(res => res.json())
.then(res => {
return {
empid: res.id,
name: res.name.preferred ? res.name.preferred : res.name.full
}
});
apiPromises.push(apiPromise)
});
Promise.all(apiPromises).then((data) => {
resolve(data);
});
}
});
};
export default peopleAPI;
Or even simpler and readable
const peopleAPI = people => {`
const apiPromises = people.map(empid => {
return fetch(`https://someApiCall/${empid}`)
.then(res => res.json())
.then(res => ({
empid: res.id,
name: res.name.preferred ? res.name.preferred : res.name.full
}));
});
return Promise.all(apiPromises)
};

async issues with js generator and promises not returning result

I'm having yet another async issue where I'm lost and have no idea where or how to fix it. Forgive my bad naming.
api call to twitch api and returns an array its results.
exports.batchPromiseWrapper = function(arr) {
const filteredMungedDataArr = [];
let promiseBatachArray = arr.map(vod_id => {
var url = `https://api.twitch.tv/kraken/videos/${vod_id.id}/markers`;
var params = { api_version: 5 };
return axios
.get(url, {
params: params,
headers: {
"Client-ID": "xxxxxxxxxxxxxxx"
}
})
.then(res => {
return res.data;
})
.catch(function(error) {
console.log(error);
});
});
return Promise.all(promiseBatachArray)
.then(markers => {
if (markers !== null) {
markers.map(markerObj => {
if (markerObj.markers.game_changes !== null) {
markerObj.markers.game_changes.forEach(gameName => {
if (gameName.label === "Fortnite") {
filteredMungedDataArr.push(markerObj);
}
});
}
});
return filteredMungedDataArr;
}
})
.catch(err => {
if (err.status === 500 || err.status === 404) {
console.log("error: ", err, err.message);
}
});
};
The data looks like this:
[[1,2,3,4,5],[1,2,3,4,5]], generator will yield and make a promise.all call of 5 before pausing 5sec and continuing to the next batch of 5.
exports.batchFetchingGeneratorWrapper = function(generator, batchArray) {
let evalNextValue = generator.next();
let delay = (v, t) => {
return new Promise(resolve => {
setTimeout(resolve.bind(null, v), t);
});
};
if (!evalNextValue.done) {
exports.batchPromiseWrapper(evalNextValue.value).then(data => {
let newBatchArray = batchArray;
if (data !== undefined) {
newBatchArray = batchArray.concat(data);
}
delay(5000).then(() => {
exports.batchFetchingGeneratorWrapper(generator, newBatchArray);
});
});
} else {
console.log("yay done!", batchArray);
return batchArray;
}
};
I'm able to console the results in batchArray from batchFetchingGeneratorWrapper, but I unable to act on it and I know it has something to do with async and how it has yet to be resolved.
promiseDataWrapper
.then(data => {
return gatherData.cleanUpVODData(data);
})
.then(data => {
function* batchFetching(batchArray) {
for (let i = 0; i < batchArray.length; i++) {
yield batchArray[i];
}
}
let batchArrResult = [];
let g = batchFetching(data);
new Promise((resolve, reject) => {
gatherData.batchFetchingGeneratorWrapper(g, batchArrResult);
if (g.done) { // i dont think this works
console.log("batchArrResult 1: ", batchArrResult);
resolve(batchArrResult);
}
}).then(result => console.log("asdfasdf", batchArrResult)); // empty array is returned
});
As far as I can tell, the problem lies chiefly in batchFetchingGeneratorWrapper().
It should be a matter of :
fixing delay()
making appropriate returns to make the recursion work
ensuring that the function returns Promise.
Almost undoubtedly (syntactically) simpler with async/await but here it is with old-fashioned thens :
exports.batchFetchingGeneratorWrapper = function(generator, batchArray) {
let evalNextValue = generator.next();
let delay = (t) => {
return new Promise(resolve => {
setTimeout(resolve, t);
});
};
if (!evalNextValue.done) {
return exports.batchPromiseWrapper(evalNextValue.value).then(data => {
return delay(5000).then(() => {
return exports.batchFetchingGeneratorWrapper(generator, batchArray.concat(data || []));
});
});
} else {
console.log("yay done!", batchArray);
return Promise.resolve(batchArray); // <<< promise wrapped to ensure that batchFetchingGeneratorWrapper() returns Promise
}
};
And chain the batchFetchingGeneratorWrapper() call appropriately :
promiseDataWrapper
.then(data => gatherData.cleanUpVODData(data))
.then(data => {
function* batchFetching(batchArray) {
for (let i = 0; i < batchArray.length; i++) {
yield batchArray[i];
}
}
return gatherData.batchFetchingGeneratorWrapper(batchFetching(data), []).then(batchArrResult => {
console.log('batchArrResult: ', batchArrResult);
return batchArrResult;
});
}).catch(error => {
console.log(error);
});

Categories