This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 5 months ago.
passed Json to array and console show empty but with objects inside.
but when printing with index console.log show undefind..
whats wrong ?
let pokeName = [];
let pokeId = [];
let pokeImg = [];
let pokeType = [];
let pokeMove = [];
for (let i=1; i< 21; i++) {
fetch(`https://pokeapi.co/api/v2/pokemon/${i}/`)
.then(Response => Response.json())
.then(data => {
pokeId.push(data['id']);
pokeName.push(data['name']);
const dataTypes = data['types'];
pokeType.push(dataTypes[0]['type']['name']);
const dataMoves = data['moves'];
pokeMove.push(dataMoves[0]['move']['name']);
pokeImg.push(data['sprites']['front_default']);
});
}
console.log(pokeName);
console.log(pokeId);
console.log(pokeImg);
console.log(pokeMove);
console.log(pokeType);
As I mentioned in my comment, your console.log() code runs before the fetch has returned its promise, and thus no data has been set yet.
for loops actually do not work with the await keyword and so typically you just need to convert your for loop to a for await...of loop instead. Then you can call an async function that loops through all the values you need and once all promises in the loop have been returned, the following code will execute (within the scope of the same function. Any code outside of the function will run asynchronously).
let pokeName = [];
let pokeId = [];
let pokeImg = [];
let pokeType = [];
let pokeMove = [];
let pokeCount = [];
for(let i = 1; i < 21; i++) pokeCount = [...pokeCount, i];
const _FetchPokes = async () => {
for await (const poke of pokeCount) {
await fetch(`https://pokeapi.co/api/v2/pokemon/${poke}/`)
.then(Response => Response.json())
.then(data => {
pokeId.push(data['id']);
pokeName.push(data['name']);
pokeType.push(data['types'][0]['type']['name']);
pokeMove.push(data['moves'][0]['move']['name']);
pokeImg.push(data['sprites']['front_default']);
});
}
// This will run AFTER the data has been fetched
_RunAfterFetch();
}
const _RunAfterFetch = () {
// Add any code you want to run here
// This will run AFTER the pokemon data has been fetched
console.log(pokeName[1-1]);
}
_FetchPokes();
Your console logs are running before your fetch calls are finishing. You can use async/await to solve the issue.
Something like this should work:
let pokeName = [];
let pokeId = [];
let pokeImg = [];
let pokeType = [];
let pokeMove = [];
(async function () {
for (let i = 1; i < 21; i++) {
const data = await fetch(`https://pokeapi.co/api/v2/pokemon/${i}/`);
const json = data.json();
pokeId.push(json['id']);
pokeName.push(json['name']);
const dataTypes = json['types'];
pokeType.push(dataTypes[0]['type']['name']);
const dataMoves = json['moves'];
pokeMove.push(dataMoves[0]['move']['name']);
pokeImg.push(json['sprites']['front_default']);
}
})();
console.log(pokeName);
console.log(pokeId);
console.log(pokeImg);
console.log(pokeMove);
console.log(pokeType);
here is the alternate way to fetch data
const getPokemon =async(id)=>{
return await (await fetch(`https://pokeapi.co/api/v2/pokemon/${id}/`)).json();
}
const getSerializedData = async () =>{
for (let i=1; i< 10; i++) {
const data = await getPokemon(i);
console.log(data)
}
}
getSerializedData();
Related
I wish to convert a CSV file with data on camping spots to a list of objects. The attributes of the shelters are separated by a semicolon and looks something like this:
X;Y;postnumber_city;name;postnumber;describtion_short;max_number_of_people
445502.7247;6212415.4577;Hvide Sande;Shelter 1;6960;3 shelters, grillplads, borde-/bænkesæt og toilet;6
My code looks like this:
const fs = require('fs');
function csvToObjects(fileName) {
fs.readFileSync(fileName, "utf-8");
let jsObj = [];
let shelters = fileName.split('\n')
for (let attributes of shelters) {
attributes = shelters.split('; ');
}
obj.push(attributes)
}
console.log(csvToObjects('shelters.csv'));
I really don't know what I am doing wrong. I get an error from attributes = shelters.split('; ');
TypeError: shelters.split is not a function
You need to put obj.push(attributes) inside for loops,and use attributes.split('; '); instead of shelters.split('; ')
function csvToObjects(fileName) {
fs.readFileSync(fileName, "utf-8");
let jsObj = [];
let shelters = fileName.split('\n')
for (let attributes of shelters) {
let data = attributes.split(';');
jsObj.push(data)
}
}
I attempted with some other for-loops and assigned a variable for my readfile, which seemed to do the job.
const fs = require('fs');
function csvToObjects(fileName) {
let file = fs.readFileSync(fileName, "utf-8");
let jsObj = [];
let shelters = file.split('\n')
let attributes = shelters[0].split(';')
for (let i = 0; i < shelters.length; i++) {
let data = shelters[i].split(';')
let obj = {};
for (let j = 0; j < data.length; j++) {
obj[attributes[j].trim()] = data[j].trim();
}
jsObj.push(obj);
}
return jsObj;
}
Why can't I extract the fields that I want from the for loop?
Console Log
JSON Data
document.addEventListener('DOMContentLoaded', function() {
let user = 'example';
fetch(`/jsonresponse/${user}`)
.then(response => response.json())
.then(data => {
// The line below works and prints the username
console.log(data['UsersInfo'][0].username)
// Doesn't work in a for Loop
for (let i = 0; i < data.length; i++) {
console.log(data['UsersInfo'][i].username);
}
});
Any hints would be appreciated
Your issue is in for loop you need to loop over data["UsersInfo"] not just data
vvvvvvvvvvvv
for (let i = 0; i < data["UsersInfo"].length; i++) {
console.log(data["UsersInfo"][i].username);
}
it's better to store user users in array and loop over them with for..of
const users = data["UsersInfo"];
for (const user of users) {
console.log(user.username);
}
Trying to get values from an API using async functions. I need to be able to access the values in the array immediately.
componentDidMount() {
var devices = this.props.navigation.state.params.userInfoState.deviceIds
async function call_vstat(device, token) {
try {
let response = await fetch(
'http://app.yatis.io/api/admin/getDeviceStatus?api_access_token=' + token + '&deviceId=' + device,
);
let responseJson = await response.json();
return responseJson;
} catch (error) {
console.error(error);
}
}
var results = []
for (i = 0; i < devices.length; i++) {
var result = call_vstat(devices[i], my_token)
.then( (result) => (results.push(result) ) )
}
console.log(results.length)
console.log(results)
}
Here's the issue when I look at the logger, I get an array of length twenty one but when logging the length itself it shows zero.
If you are using async await you don't have to use the then(). What you can do is
for (i = 0; i < devices.length; i++) {
var result = await call_vstat(devices[i], my_token)
results.push(result)
}
Hope this works
As mentioned in my comments,
var promiseArray = [];
for (i = 0; i < devices.length; i++) {
promiseArray.push(call_vstat(devices[i], my_token));
}
var results = await Promise.all(promiseArray);
if (results.length > 0) {
//perform your business logic after this check to avoid any errors
}
This question already has answers here:
Waiting for promise in for loop
(2 answers)
Closed 4 years ago.
I have a state this.state = { PathBased : [] , ...ect}
and a function containing a for loop ,after looping this.state.data I want to add every returned element of the for loop to PathBased state ,
I can't find how to do it , could you please help
by the way
console.log(this.state.data) output is 5
async readFromLocal (){
let dirs = RNFetchBlob.fs.dirs;
let path = [];
let leng = this.state.data.length;
if(leng > 0)
{
for( var j = 0 ; j < leng; j++)
{
path[j] = dirs.PictureDir+"/folder/"+this.state.data[j].title;
const xhr = RNFetchBlob.fs.readFile(path[j], 'base64')
.then ((data) => {this.setState({PathBased:[...PathBased,data]})})
.catch ((e) => {e.message});
}
}
console.log(this.state.PathBased.length) // output = 0
}
You could make use of Promise.all and set the final result in the PathBased state. Also since setState is async you need to check the updated state in setState callback.
async readFromLocal (){
let dirs = RNFetchBlob.fs.dirs;
let path = [];
let promises = [];
let leng = this.state.data.length;
if(leng > 0) {
for( let j = 0 ; j < leng; j++) {
path[j] = dirs.PictureDir+"/folder/"+this.state.data[j].title;
promises.push(RNFetchBlob.fs.readFile(path[j], 'base64'))
}
}
Promise.all(promises)
.then(data => this.setState({PathBased: data}, () => {console.log(this.state.PathBased)})
)
.catch(e => {console.log(e.message)});
}
I am modernizing some code. It has a piece to load database implemented as:
var customerQueue = async.queue(insertCustomer, DATABASE_PARALLELISM);
customerQueue.drain = function() {
logger.info('all customers loaded');
airportCodeMappingQueue.push(airportCodeMappings);
}
The function insertCustomer used to written with callbacks. I changed it to async/await, as a part of code modernization.
Now, think that I wrote an equivalent of async.queue as:
let customerQueueElements = [];
var customerQueue = {};
customerQueue.push = (customers) => {
customers.forEach(customer => {
customerQueueElements.push(insertCustomer(customer))
});
}
const processQueue = async (queue, parallelism) => {
for (let i = 0; i < queue.length; i += parallelism) {
for (let j = 0; j < parallelism; j++) {
let q = []
if (queue[i + j]) {
q.push(queue[i + j])
}
await Promise.all(q)
}
}
}
I am able now to do await ProcessQueue(customerQueue, DATABASE_PARALLELISM), but the syntax is bad, and I am keeping a visible named variable for each queue.
What would be a good way to handling this?
Also, drain() should be hooked-up to then, right ?
#Bergi is correct, as far as direction. I put together a work-in-process version:
module.exports = function () {
module.internalQueue = []
module.func = undefined
module.parallelism = 1
const process = async () => {
for (let i = 0; i < module.internalQueue.length; i += module.parallelism) {
for (let j = 0; j < module.parallelism; j++) {
let q = []
if (module.internalQueue[i + j]) {
q.push(module.func(module.internalQueue[i + j]))
}
await Promise.all(q)
}
}
module.internalQueue = []
module.drain()
}
module.queue = (func, parallelism = 1) => {
module.func = func
module.parallelism = parallelism
return module
}
module.push = async (customers) => {
module.internalQueue.push(customers)
await process()
}
module.drain = () => {}
return module
}
It is not exactly correct, yet. The signatures are similar to the async package, but my version shares the queue among all instances.
Need to figure out an easy way of creating an instance for each function with a separate e.g. "local" queue. Then, it will basically work like the original one.
Will update as I have progress.