Having some confusion around how to properly handle javascript promises with axios - javascript

So I have two simple functions, the first function makes an api call and retrieves 100 category ids and stores them in an array. I use lodash to randomly pick 6 of these category ids. The second function is suppose to make use of these 6 unique category ids and use them in the query string for the next 6 api calls made in the second function.
async function getCategoryIds() {
const res = await axios.get('http://jservice.io//api/categories?count=100');
for (let cat of res.data) {
categories.push(cat.id)
}
var sampleCategories = _.sampleSize(categories, 6);
console.log(sampleCategories);
return sampleCategories;
}
getCategoryIds()
.then(getCategory)
async function getCategory(sampleCategories) {
const res1 = await axios.get(`http://jservice.io/api/category?id=${sampleCategories[0]}`);
const res2 = await axios.get(`http://jservice.io/api/category?id=${sampleCategories[1]}`);
const res3 = await axios.get(`http://jservice.io/api/category?id=${sampleCategories[2]}`);
const res4 = await axios.get(`http://jservice.io/api/category?id=${sampleCategories[3]}`);
const res5 = await axios.get(`http://jservice.io/api/category?id=${sampleCategories[4]}`);
const res6 = await axios.get(`http://jservice.io/api/category?id=${sampleCategories[5]}`);
}
getCategory();
However, no matter how I rework it I still cannot get this error to go away:
Uncaught (in promise) TypeError: Cannot read property '0' of undefined
Could somebody steer my in the right direction?
Thank you.

if your backend is exactly sending response an exact array then you should
dont forget to give args when u r calling getCategory function
then edit your getCategory function
async function getCategory(sampleCategories) {
let arr = []
const res1 = await axios.get('any url you want')
//repeat 6 times
arr = [res1, res2, ...otherElems]
return arr
}
with 'then' syntax
getCategoryIds()
.then(response => getCategory(response))
with async await syntax
const firstResponseArr = await getCategoryIds();
const secondResponseArr = await getCategory(firstResponseArr);

Your Mistake
Calling getCategory(); with passing any argument. Clearly async function getCategory(sampleCategories) needs an argument - sampleCategories which you failed to pass.
Error intepretation
Uncaught (in promise) TypeError: Cannot read property '0' of undefined # sampleCategories
Call getCategory() with an argument
This has nothing to do with axios but with your careless mistake. (Don't worry, it happens to even the best of us)

Alright so what I was struggling with was trying to figure out how to properly utilize async/await -- this seemed to work for me:
let categories = []
var sampleCategories = []
async function getCategoryIds() {
const res = await axios.get('http://jservice.io//api/categories?count=100');
for (let cat of res.data) {
categories.push(cat.id)
}
var sampleCategories = _.sampleSize(categories, 6);
return sampleCategories;
}
getCategoryIds()
async function getCategory() {
var y = await getCategoryIds();
const res1 = await axios.get(`http://jservice.io/api/category?id=${y[0]}`);
const res2 = await axios.get(`http://jservice.io/api/category?id=${y[1]}`);
const res3 = await axios.get(`http://jservice.io/api/category?id=${y[2]}`);
const res4 = await axios.get(`http://jservice.io/api/category?id=${y[3]}`);
const res5 = await axios.get(`http://jservice.io/api/category?id=${y[4]}`);
const res6 = await axios.get(`http://jservice.io/api/category?id=${y[5]}`);
let arr = [res1, res2, res3, res4, res5, res6]
return arr
}
getCategory();

Related

Fetch text from url then stringify it

So i have just started to learn javascript today and i'm trying to fetch text from a url and then split and stringify it using josn.
Then i'm trying to pick a random proxy from the stringify json and log it in my self invoking function but it logs as undefined and i can't workout what i'm doing wrong and i was hoping maybe someone could tell me what i'm doing wrong.
My code:
const doFetch = async () => {
try {
let proxies = [];
let socks = await fetch("https://raw.githubusercontent.com/TheSpeedX/PROXY-List/master/socks4.txt");
let response = await socks.text();
let list = response.toString().split('\n');
for (let i = 0; i < list.length; i++) {
let splitText = list[i].split(':');
proxies.push(JSON.stringify({'type': 'socks4', 'ip': splitText[0], 'port': splitText[1]}));
}
return proxies
} catch (error) {
console.log('fetch error:', error.message);
}
}
(async () => {
let proxies = await doFetch();
let proxie = proxies[Math.floor(Math.random() * proxies.length)];
console.log(proxie); // logs fine
console.log(proxie.type, proxie.ip, proxie.port); // logs as undefined
})();
proxie.type, proxie.ip, proxie.port are undefined because proxie is a string and not an object. Rewrite your code in this way:
(async () => {
let proxies = await doFetch();
let proxie = proxies[Math.floor(Math.random() * proxies.length)];
console.log(proxie); // logs fine
let proxieObj = JSON.parse(proxie);
console.log(proxieObj.type, proxieObj.ip, proxieObj.port);
})();

There are 2 identical receive values ​from a promise: in one case it works, in another it gives an TypeError: x is not a function

I use the element search in my autotest and take the name from the list. My code works, everything is fine. But in autotest I use this code several times. Therefore, I decided to put it into a function and call it when I need to.
Code operates:
await driver.wait(until.elementLocated(By.className("item")), 20000);
let findItems1 = await driver.findElements(By.className("item"));
let items1 = findItems1.map(async elem => await elem.getText());
await Promise.all(items1);
let currentItem1 = findItems1[findItems1.length - 1];
await currentItem1.click();
currentName = await currentItem1.getText(); // This string operates
await Promise.all(currentName)
console.log(currentName)
I infer the value of the variable from the function in which the promise lies. I can click on this item. But when I want to get a text value from a promise, the string "currentName = await currentItem1.getText()" throws an error. Although in my first code this line works. I don’t understand what could be the reason.
Code doesn't operate:
async function findCurrentItem(){
await driver.wait(until.elementLocated(By.className("item")), 20000);
let findItems = await driver.findElements(By.className("item"));
let items = findItems.map(async elem => await elem.getText());
await Promise.all(items);
let currentItem = findItems[findItems.length - 1];
return currentItem;
}
let current = findCurrentItem();
await currentItem1.click();
console.log(current, 1) // console displays promise
let currentName = await current.getText(); // This string doesn't operate
await Promise.all(currentName)
console.log(currentName, 2) // console displays error
Error:
TypeError: currentItem.getText is not a function
What can I do?
You made findCurrentItem async function but don't await its result when using it.
Change to let current = await findCurrentItem();

How can I access and use a return value from a do while loop?

I am trying to access return data from a do while loop, but I am unable to do so.
I have stored the information in a new variable (starships) and then returned this variable, but it says starships is not defined. I see that this may be a scoping issue, how can I resolve this?
async function getData() {
const allResults = [];
let url = 'https://swapi.co/api/starships/';
do {
const res = await fetch(url);
const data = await res.json();
url = data.next;
allResults.push(...data.results);
console.log(allResults);
} while (url !== null)
let starships = allResults;
return starships;
}
console.log(starships);
You need to get the value which is returned from getData. The most obvious way to do this with the async/await structure you have is to just await it:
async function getData() {
const allResults = [];
let url = 'https://swapi.co/api/starships/';
do {
const res = await fetch(url);
const data = await res.json();
url = data.next;
allResults.push(...data.results);
console.log(allResults);
} while (url !== null)
let starships = allResults;
return starships;
}
async function doTheDo() {
const test = await getData();
console.dir(test);
}
doTheDo();
you can do this. starships is defined inside the loop. Additionally, you are not calling getData() function. You can store that return value like this
const result = await getData();
console.log(result);
or you can directly print like this. console.log(await getData())
async function getData() {
const allResults = [];
let url = 'https://swapi.co/api/starships/';
do {
const res = await fetch(url);
const data = await res.json();
url = data.next;
allResults.push(...data.results);
console.log(allResults);
} while (url !== null)
return allResults;
}
console.log(await getData());
Async functions return a promise, which means you have to access the return value with a .then().
However, you have another problem: starships is in the scope of the function getData() which you have defined, but not called.
So first lets call your function:
async function getData() {
const allResults = [];
// do stuff
let starships = allResults;
return starships;
}
console.log(getData());
Now you will see that your log value is [object Promise] which isn't so helpful in its current form. This is because the code outside the async function is running synchronously, which means we don't have the value yet, just a promise to maybe return the value sometime in the future.
So now we need to access the promise asynchronously using the .then() like so:
async function getData() {
const allResults = [];
// do stuff
let starships = allResults;
return starships;
}
getData().then(starships => {
console.log(starships);
});
Now you should see the info you were expecting to be logged.
You can also save promise to a variable and pass it around and access it elsewhere in your code like so:
async function getData() {
const allResults = [];
// do stuff
let starships = allResults;
return starships;
}
let starshipPromise = getData();
// time & code passes...
starshipPromise.then(starship => {
console.log(starship);
}).catch(error => {
// handle error
});
And don't forget to catch your rejected promises!
See the MDN docs on Async functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
And if you need more info on promises, go here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

angular 6 wait post response

var data2 = { data1Id: 0 };
postData(){
this._service1.save(data1).subscribe(res => {
this.data2.data1Id = res.Data.Id; //res.Data.Id has valid data
});
this._service2.save(data2).subscribe(res => {
console.log(this.data2.data1Id); //"this.data2.data1Id = 0" can't get value from service1
});
}
how can i get data from the first service or some function take me resolve problem run call service sequence. thank for watching !
Using async/await is perfect for your situation. It will help you to make your code more readable and make abstraction of the async part thanks to the await keyword
aync post(){
const res1 = await this._service1.save(this.data1).toPromise();
const res2 = await this._service2.save(res1).toPromise();
console.log('here is my data 2 ' + res2);
return 'what you want, can be res1 or res2 or a string';
}
How to call it ?
this.myService.post().then( (whatYouWanted) => {
console.log(whatYouWanted); // what you want, can be res1 or res2 or a string
});
this._service1.save(data1).flatMap(res => {
this.data2.data1Id = res.Data.Id; //res.Data.Id has valid data
return this._service2.save(data2);
}).subscribe(res => {
console.log(this.data2.data1Id); //"this.data2.data1Id = 0" can't get value from service1
});
You can use flatMap and return the second observable to chain them.
Documentation: http://reactivex.io/documentation/operators/flatmap.html

Promise/async-await with mongoose, returning empty array

The console in the end returns empty array.
The console runs before ids.map function finishes
var ids = [];
var allLync = []
var user = await User.findOne(args.user)
ids.push(user._id)
user.following.map(x => {
ids.push(x)
})
ids.map(async x => {
var lync = await Lync.find({ "author": x })
lync.map(u => {
allLync.push[u]
})
})
console.log(allLync)
What am I doing wrong?
The .map code isn't awaited, so the console.log happens before the mapping happens.
If you want to wait for a map - you can use Promise.all with await:
var ids = [];
var allLync = []
var user = await User.findOne(args.user)
ids.push(user._id)
user.following.map(x => {
ids.push(x)
})
// note the await
await Promise.all(ids.map(async x => {
var lync = await Lync.find({ "author": x })
lync.map(u => {
allLync.push(u); // you had a typo there
})
}));
console.log(allLync)
Note though since you're using .map you can shorten the code significantly:
const user = await User.findOne(args.user)
const ids = users.following.concat(user._id);
const allLync = await Promise.all(ids.map(id => Lync.find({"author": x })));
console.log(allLync);
Promise.map() is now an option that would be a tiny bit more succinct option, if you don't mind using bluebird.
It could look something like:
const user = await User.findOne(args.user);
const ids = users.following.concat(user._id);
const allLync = await Promise.map(ids, (id => Lync.find({"author": x })));
console.log(allLync);
http://bluebirdjs.com/docs/api/promise.map.html. I have really enjoyed using it.

Categories

Resources