I'm doing an operation inside my function and I want to store my JSON data with AsyncStorage and use it elsewhere, but I'm getting an error in react native
this is my code block;
onPress={() => {
press = item.id;
// console.warn(press);
ars = options;
dd = JSON.stringify(ars);
cc = JSON.parse(dd);
for (var i = 0; i < cc.length; i++) {
if (cc[i].id == press) {
// console.warn(cc[i]);
var productData = cc[i];
var stri = JSON.stringify(cc[i]);
AsyncStorage.setItem('ProductData', stri);
var abc = AsyncStorage.getItem('ProductData');
console.warn(stri);
console.warn(abc);
}
}
}}>
how can i solve that problem?
thanks.
var abc = await AsyncStorage.getItem('ProductData');
add await as it is promise that all
so whole code will look like this
onPress={async () => {
press = item.id;
// console.warn(press);
ars = options;
dd = JSON.stringify(ars);
cc = JSON.parse(dd);
for (var i = 0; i < cc.length; i++) {
if (cc[i].id == press) {
// console.warn(cc[i]);
var productData = cc[i];
var stri = JSON.stringify(cc[i]);
AsyncStorage.setItem('ProductData', stri);
var abc =await AsyncStorage.getItem('ProductData');
console.warn(stri);
console.warn(abc);
}
}
}}>
add async to function and add await
Related
async postList(arr){
console.log(arr);
console.log(arr[0]);
Debugger + console picture: https://prnt.sc/23q4jra
as seen in the picture of the debugger console.log(arr) returns an array with a value in the [0] position, the very next line arr[0] returns "undefined" and arr.length returns "0"
how is it possible?
the function that calls this function:
async mountedCall(){
var composedArray = await this.createList();
document.getElementById('listWrap_players').appendChild(await this.postList(composedArray));
},
createList():
async createList(){
var composedArray = [];
const id = document.getElementById('joinCode').innerHTML;
var player_count = null;
await firebase.database().ref('lobbies/' + id + '/playerCount/').once('value', (snapshot) => {
const data = snapshot.val();
player_count = data;
}).then(function() {
for(var i = 1; i <= player_count; i++){
var iStr = String(i);
const player_names_snapshot = firebase.database().ref('lobbies/' + id + '/players/' + iStr);
player_names_snapshot.once('value', (snapshot) => {
const data = snapshot.val();
composedArray.push(data);
}).then(function(){return;});
}
});
this.isLeader(id);
return composedArray;
},
UPDATE:
Tried to replace console.log with console.log(JSON.stringify(arr)) as suggested below
console.log(JSON.stringify(arr)) returns an empty array so I think it means I have synchronization problem in createList() or in mountedCall(), yet I cant seem to find it. I've used await and .then() in every location possible...
here are all the functions together:
async mountedCall(){
var composedArray = await this.createList();
document.getElementById('listWrap_players').appendChild(await this.postList(composedArray));
},
async removeAllChildNodes(list) {
while(list.firstChild){
list.removeChild(list.firstChild);
}
},
async postList(arr){
console.log(JSON.stringify(arr));
console.log(arr[0]);
var list = document.createElement('ul');
for(let i = 0; i < arr.length; i++){
var item = document.createElement('li');
item.appendChild(document.createTextNode(arr[i]));
list.appendChild(item);
}
const listContainer = document.getElementById('listWrap_players');
this.removeAllChildNodes(listContainer);
return list;
},
async createList(){
var composedArray = [];
const id = document.getElementById('joinCode').innerHTML;
var player_count = null;
await firebase.database().ref('lobbies/' + id + '/playerCount/').once('value', (snapshot) => {
const data = snapshot.val();
player_count = data;
}).then(function() {
for(var i = 1; i <= player_count; i++){
var iStr = String(i);
const player_names_snapshot = firebase.database().ref('lobbies/' + id + '/players/' + iStr);
player_names_snapshot.once('value', (snapshot) => {
const data = snapshot.val();
composedArray.push(data);
}).then(function(){return;});
}
});
return composedArray;
},
I'm having problem with loading from local storage.
Here's a part of the code
const getTerminus = () => {
let terminus;
if (localStorage.getItem("terminus") === null) {
terminus = [];
} else {
terminus = JSON.parse(localStorage.getItem("terminus"));
}
let directions;
if (localStorage.getItem("directions") === null) {
directions = [];
} else {
directions = JSON.parse(localStorage.getItem("directions"));
}
terminus.forEach(async(stop) => {
let API_URL =
"https://ckan.multimediagdansk.pl/dataset/c24aa637-3619-4dc2-a171-a23eec8f2172/resource/d3e96eb6-25ad-4d6c-8651-b1eb39155945/download/stopsingdansk.json";
let response = await fetch(API_URL);
let data = await response.json();
const {
stops,
stopId,
stopName,
stopCode,
zoneId
} = data;
let input = stop;
let ID;
let dataArr = [];
for (let i = 0; i < stops.length; i++) {
if (
stops[i].stopName === input &&
stops[i].stopCode === directions[terminus.indexOf(input)] &&
stops[i].zoneId === 1
) {
ID = stops[i].stopId;
dataArr = [ID, stops[i].stopName];
}
}
API_URL = `https://ckan2.multimediagdansk.pl/delays?stopId=${ID}`;
response = await fetch(API_URL);
data = await response.json();
const {
delay,
estimatedTime,
routeId,
headsign
} = data;
let times = [];
let routeIds = [];
let headsigns = [];
for (let i = 0; i < delay.length; i++) {
times.push(delay[i].estimatedTime);
routeIds.push(delay[i].routeId);
headsigns.push(delay[i].headsign);
}
routeIds.push(" ");
times.push(" ");
const cardDiv = document.createElement("div");
cardDiv.classList.add("card");
const stopNameDiv = document.createElement("div");
stopNameDiv.classList.add("stop-name-div");
cardDiv.appendChild(stopNameDiv);
const stopNameSpan = document.createElement("span");
stopNameSpan.innerText = dataArr[1];
stopNameSpan.classList.add("stop-name-span");
stopNameDiv.appendChild(stopNameSpan);
const scheduleDiv = document.createElement("div");
scheduleDiv.classList.add("schedule-div");
cardDiv.appendChild(scheduleDiv);
if (headsigns.length !== 0) {
routeIds.unshift("Line");
headsigns.unshift("Direction");
times.unshift("Departure");
}
const lineSpan = document.createElement("span");
lineSpan.innerText = routeIds.join("\n");
lineSpan.classList.add("line-span");
scheduleDiv.appendChild(lineSpan);
const dirSpan = document.createElement("span");
dirSpan.innerText = headsigns.join("\n");
dirSpan.classList.add("dir-span");
scheduleDiv.appendChild(dirSpan);
const timeSpan = document.createElement("span");
timeSpan.innerText = times.join("\n");
timeSpan.classList.add("time-span");
scheduleDiv.appendChild(timeSpan);
const buttonsDiv = document.createElement("div");
buttonsDiv.classList.add("buttons-div");
cardDiv.appendChild(buttonsDiv);
const deleteButton = document.createElement("button");
deleteButton.innerHTML = '<i class="fas fa-trash"></i>';
deleteButton.classList.add("delete-button");
buttonsDiv.appendChild(deleteButton);
const dirButton = document.createElement("button");
dirButton.innerHTML = '<i class="fas fa-retweet"></i>';
dirButton.classList.add("reverse-button");
buttonsDiv.appendChild(dirButton);
stopList.appendChild(cardDiv);
});
};
document.addEventListener("DOMContentLoaded", getTerminus);
Terminus contains stop names, and directions contains direction codes.
On refresh, it fetches data from API based on stop name and direction, and displays a card with departure time etc.
The problem is, on closing and re-opening the page cards are sometimes displayed in a wrong order. I have found out, that as time between closing and opening lengthens, the probability of this occurring gets higher. After simple refresh everything is in correct order.
Does it have something to do with browser cache? Has anyone had similar issue or knows what's going on?
Alright, as #Yoshi stated, it was insequential promise error. I managed to fix it by using reduce().
Here are the threads that helped me
Resolve promises one after another (i.e. in sequence)?
Why Using reduce() to Sequentially Resolve Promises Works
I want my filters variable to update, my guess is it's re-initializing as the set value every time the function is called, whenever i try to declare it outside of the function I get a lexical error, how can I make sure it keeps the value assigned to it after a button has clicked
export function categoryRender(){
let filter = 'RICK'
console.log(filter)
const all = document.getElementById('all');
all.onclick = function(){
filter = 'ALL'
render(filter);
}
categories = categories.sort();
const filterContainer = document.getElementById("filter-container");
filterContainer.innerHTML = "";
const allFilterImg = document.getElementById('all-image');
if (filter === 'ALL'){
allFilterImg.setAttribute('src', './images/checked.jpeg')
}else{
allFilterImg.setAttribute('src', './images/unchecked.png')
console.log('unchecked all firing')
}
for (let i = 0; i < categories.length; i++){
const line = document.createElement("span");
const filterButton = document.createElement("img");
const filterLabel = document.createElement("h2");
filterContainer.appendChild(line);
line.appendChild(filterButton);
line.appendChild(filterLabel);
line.setAttribute('id', categories[i]);
line.classList.add('filter-line');
filterLabel.innerHTML = categories[i];
if (filter === categories[i]){
filterButton.setAttribute('src', './images/checked.jpeg')
}else{
filterButton.setAttribute('src', './images/unchecked.png')
}
line.onclick = function(){
filter = categories[i];
render(filter)
}
}
}
I’m building a site using sapper and requesting data from an API. It has been working smooth until now.
When I’m going from site.com/title/id1 to site.com/title/id2 the new information is not loaded until I hit a manual refresh. Any ideas?
import { stores, goto } from "#sapper/app";
import Card from "../_titlecard.svelte";
const { page } = stores();
const { slug } = $page.params;
import { onMount } from "svelte";
let looper = [];
let artistName = "";
let titleName = "";
let dvdCover = "";
let titleCover = "";
let genre = "";
let tracks = [];
onMount(async () => {
const res = await fetch(`https://.com/api/title/${slug}`);
const data = await res.json();
artistName = data.artistName;
titleName = data.name;
dvdCover = data.graphics.dvd;
titleCover = data.graphics.landscape;
genre = data.genre;
tracks = data.tracks.length;
const res2 = await fetch(`https://.com/api/artists/all`);
const data2 = await res2.json();
let moreTitles = [];
const more = data2.map((x) => {
if (x.titles.length > 0 && x.genre === genre) {
looper.push(x.titles[0]);
looper = moreTitles;
}
});
});
And then I have this in the html
{#each looper.slice(0, 4) as item, i}
<Card imgurl={item.graphics.dvd} concert={item.name} id={item.id} />
{/each}
A page component is not unmounted and mounted again if the navigation results in the same page component being used, so your onMount will only be run once with the first id.
You could use a reactive statement to make sure you run the desired code every time $page.params.slug changes.
Example
import { stores, goto } from "#sapper/app";
import Card from "../_titlecard.svelte";
const { page } = stores();
let looper = [];
let artistName = "";
let titleName = "";
let dvdCover = "";
let titleCover = "";
let genre = "";
let tracks = [];
$: (async () => {
const { slug } = $page.params;
const res = await fetch(`https://.com/api/title/${slug}`);
const data = await res.json();
artistName = data.artistName;
titleName = data.name;
dvdCover = data.graphics.dvd;
titleCover = data.graphics.landscape;
genre = data.genre;
tracks = data.tracks.length;
const res2 = await fetch(`https://.com/api/artists/all`);
const data2 = await res2.json();
let moreTitles = [];
data2.forEach((x) => {
if (x.titles.length > 0 && x.genre === genre) {
moreTitles.push(x.titles[0]);
}
});
looper = moreTitles;
})();
I'm having a problem where for(var x=1; x < 6; x++) is getting called because too fast axios.get() is async, but I have no idea how to counter that without the solution being too complicated
const axios = require("axios");
const cheerio = require("cheerio");
function imdbGetData(id) {
var title, show, $;
var arr = [];
var airdates = [];
show = {
seasons: []
};
axios.get(`http://www.imdb.com/title/${id}/`).then((body) => {
$ = cheerio.load(body.data);
title = $("div h1").text()
});
for(var x=1; x < 6; x++) {
console.log(x); // Will count too 1,2,3,4,5,6
url = `http://www.imdb.com/title/${id}/episodes?season=${x}`
axios.get(url).then((body) => {
$ = cheerio.load(body.data);
console.log(x);// 6, 6, 6, 6
$("div .info .airdate").each(function(index, item) {
var airdate = String($(this).text());
airdates.push(airdate.trim());
});
$(".info strong a").each(function(i, item){
var airdate = airdates[i];
var epsiode_name = $(this).text()
if (epsiode_name && !epsiode_name.includes("#"))
arr.push({epsiode_name, airdate});
});
show.seasons.push(arr);
arr = []
// console.log(show.seasons);
});
setTimeout(() => {console.log(show.seasons)}, 10000) // ghetto
}
}
// season = {
// seasons: [[ {epsiode_name} ], [{Epsiode name}]]
// }
imdbGetData("tt2193021");
You can construct and push all promises to array, and then use Promise.all(arrayOfPromises). This way you will keep your asynchronous chain and you can easily handle results very similar to regular single asynchronous operation:
var promises = [];
for (var x = 1; x < 6; x++) {
url = `http://www.imdb.com/title/${id}/episodes?season=${x}`
promises.push(axios.get(url));
}
Promise.all(promises)
.then(body => {
// all results of promises will be in 'body' parameter
})
.catch(err => console.error(err));
You can also use async/await (in newer versions of Node.js), so you can make the code a little easier to read, I've made a few little changes to update progress too.
const axios = require("axios");
const cheerio = require("cheerio");
async function imdbGetData(id) {
var title, show, $;
var arr = [];
var airdates = [];
show = {
seasons: []
};
console.log('Getting from ' + `http://www.imdb.com/title/${id}/`);
let body = await axios.get(`http://www.imdb.com/title/${id}/`);
$ = cheerio.load(body.data);
title = $("div h1").text()
for(var x=1; x < 6; x++) {
console.log('Getting season: ' + x); // Will count too 1,2,3,4,5,6
url = `http://www.imdb.com/title/${id}/episodes?season=${x}`
let body = await axios.get(url);
$ = cheerio.load(body.data);
$("div .info .airdate").each(function(index, item) {
var airdate = String($(this).text());
airdates.push(airdate.trim());
});
$(".info strong a").each(function(i, item){
var airdate = airdates[i];
var epsiode_name = $(this).text()
if (epsiode_name && !epsiode_name.includes("#"))
arr.push({epsiode_name, airdate});
});
show.seasons.push(arr);
arr = []
}
console.log("Result: ", show.seasons);
}
imdbGetData("tt2193021");
You can simply use ES6 let instead of var , your code will be:
for(let i=0; i<length; i++){
asyncCall(function(){
console.log(i);// will print 0,1,2,3,...
});
}
Please check this article https://codeburst.io/asynchronous-code-inside-an-array-loop-c5d704006c99