Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
Does anyone have any idea why i is not defined in this loop? i cannot figure it out...
I'm trying to paginate through the pages of data received from an api and gather it all into one array and store it in state, but my for loop doesn't seem to be working because of the error: "i is not defined"
how else should i go about this???
gatherAllCharacters = () => {
fetch(`https://rickandmortyapi.com/api/character/`)
.then(res => res.json())
.then(data => {
let characters = data.results;
const totalPages = data.info.pages;
if (totalPages > 1) {
for (i = 2; i <= totalPages; i++) {
let page = i;
fetch(`https://rickandmortyapi.com/api/character/?page=${i}`)
.then(res => res.json())
.then(data => {
characters = characters.concat(data.results);
if (page === totalPages) {
this.setState({ allCharacters: characters });
}
});
}
} else {
console.log("none");
}
});
};
You can create a for loop like you have done above
for (i = 2; i <= totalPages; i++) {
//perform loop
}
However this generates a variable i in the global namespace and this is generally speaking a bad idea.
therefore you should initialise i before using it like so:
for (let i = 2; i <= totalPages; i++) {
//perform loop
}
Therefore ECMA decided to have a mode where this (and my other features that would cause undesirable side effects would instead throw an error).
see more here https://www.w3schools.com/js/js_strict.asp
As your app is in use-strict mode it will be throwing the error "i is not defined"
Remember to initialize any variable before using it!
Couple things you should know about let and var
var and let can change their value and const cannot change its value
var can be accessible anywhere in function but let and const can only be accessible inside the block where they are declared.
Because i is not defined. You need a var or let in front of i to define a new variable.
for(let i = 2; i <= totalPages; i++ )
- for (i = 2; i <= totalPages; i++) {
+ for (let i = 2; i <= totalPages; i++) {
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 months ago.
Improve this question
Hello I'm new to JS and fetch api. I'm facing a problem that the following code perfectly works and show the datas from that api when I run that code with node and display in on the console. But when I try to show the datas from the api to the browser with JS DOM , it shows 403 error even though I include the authentication in the headers.
fetch('https://od-api.oxforddictionaries.com/api/v2/entries/en-gb/arrow'
, {
method: 'GET',
mode: 'no-cors',
headers: { app_id: "api_id", app_key: "api_key" },
})
.then((response) => response.json())
.then((data) => {
let noun = document.querySelector("#forNoun")
let verb = document.querySelector("#forVerb")
let nounEg = document.querySelector("#nounEg")
let verbEg = document.querySelector('#verbEg')
let searchbtn = document.getElementById("search")
let searchWord = document.getElementById("word")
let nounDef = document.createElement("p");
let verbDef = document.createElement("p")
let lexicalEntries = data.results[0].lexicalEntries;
let length = lexicalEntries.length
for (let i = 0; i < length; i++) {
console.log(lexicalEntries[i].lexicalCategory.text);
nounVerb.innerHTML = lexicalEntries[i].lexicalCategory.text
let senses = lexicalEntries[i].entries[0].senses;
for (let x = 0; x < senses.length; x++) {
if ("examples" && 'synonyms' in senses[x]) {
// console.log(senses[x].definitions[0])
noun.append(senses[x].definitions[0])
}
else if ('examples' in senses[x]) {
noun.append(senses[x].definitions[0])
// console.log(senses[x].definitions[0])
}
else if ('synonyms' in senses[x]) {
noun.append(senses[x].definitions[0])
// console.log(senses[x].definitions[0])
}
else {
noun.append(senses[x].definitions[0])
// console.log(senses[x].definitions[0])
}
}
}
});
`
Inside the function in the screenshot, I am adding the data from the backend function to the array with axios.get. But when I go outside of axios, the values of the array I print are undefined.
I am getting string value from backend. I want to be able to use it in different methods by returning it. Please help me. I can't find the solution.
getReasonsForWaitingCustomer() {
this.adimKodlariLastString = "";
if (this.$route.params.status == "musteri-bekleniyor") {
axios.get(URL + "xxx/xxx?xxx=xxx)
.then(response => {
for (var i = 0; i < response.data.data.length; i++) {
if (this.stepCode.includes(response.data.data[i].adim_kodu) == false) {
this.stepCode.push(response.data.data[i].adim_kodu);
}
}
for (var j = 0; j < this.stepCode.length; j++) {
this.adimKodlari += this.stepCode[j] + ",";
}
this.adimKodlariLastString = this.adimKodlari.slice(0, -1);
console.log("inAxiosThen",this.adimKodlariLastString);
})
}
console.log("afterAxios",this.adimKodlariLastString);
return "apfapofapkapfka" --> It's working
return this.adimKodlariLastString --> It's not working. I want this to work.
},
In the solution examples I reviewed, the incoming value was used in the html tags. But I want to be able to use incoming value in methods.
When the string values I want to use are in .then(response), I can get them when I press the console.
When I press the console other than .then() I don't get the values.
You won't get any data this way because axios calls are asynchronous. The easiest and cleaner way is:
const response = await axios.get('url')
console.log(response.data)
this.adimKodlariLastString = response.data
// and then you could do your logic
Alternatively, to have it working with your code, you could just add:
await
before axios (you could do it with pure Promises but you'll end up getting Promise inside Promise).
Current,this is my function's last status. This is working. Return is successfull.
async getReasonsForWaitingCustomer() {
let adimKodlariLastString = "";
let stepCode = [];
let adimKodlari = "";
if (this.$route.params.status == "xxx") {
const response = await axios.get(URL + "xxx/xxx");
for (var i = 0; i < response.data.data.length; i++) {
if (stepCode.includes(response.data.data[i].adim_kodu) == false) {
stepCode.push(response.data.data[i].adim_kodu);
}
}
for (var j = 0; j < stepCode.length; j++) {
adimKodlari += stepCode[j] + ",";
}
adimKodlariLastString = adimKodlari.slice(0, -1);
}
console.log("adimKodu",adimKodlariLastString);
return adimKodlariLastString;
},
Promise in console
I looked at their solutions, but I didn't understand anything. In the solutions they manually assigned a value and called the result. I have no idea how to get my incoming data in PromiseResult.
Good news. I founded solution of this problem. I hope it will be useful for those who are looking for a solution. As I mentioned, I said that I wanted to use the value that came as a prompt in another function.
I'm successfully called my values in this function
I'm converted this function the async. I brought the first function as await.
Last result in the console
Community,
i am having some problems with my Angular 6 - App which i'm unfortunately not able to solve after hours of thinking & searching on google.
I've got a component that is displaying Meetings, Projects and Tasks in a Form. Those forms require a lot of data from different collections to select from (if the user wants to change something). All of those are being loaded in my ngOnInit:
ngOnInit() {
this.meetServ.getCompanyMeetings(false)
.subscribe(data => this.meetings = data as meeting[]);
this.deptServ.getCompanyDepartments()
.subscribe(data => this.depts = data as department[]);
this.CusServ.getCompanyCustomers()
.subscribe(data => this.customers = data as customer[]);
this.UserServ.getCompanyUsers()
.subscribe(data => {
this.users = data as user[];
})
}
When I'm done loading all the data, I want to set all of the dropdown menus to the right values. So I put a setDropdowns method in the subscription of the last http-request I am doing (also tried out of subscription).
The extend() Method is called by onclick event as soon as the User selects a Meeting:
extend(meetingID) {
document.getElementById("overlay").remove()
this.meetServ.getMeetingbyID(meetingID)
.subscribe(data => {
this.singleMeeting = data as meeting
this.init(); //gets all the projects by ID of selected Meeting
this.setMeetingAccessLevel();
this.setMeetingComments();
this.setDropdowns(); // tried like this
})
this.setDropdowns(); // and like this
}
and my setDropdowns() Method looks like this:
setDropdowns() {
var projectDivs = document.querySelectorAll("div.projectContent");
console.log(this.projects.length)
for (var i = 0; i < this.projects.length; i++) {
// Access Level
var opts = projectDivs[i].querySelector("#access").querySelectorAll("option");
(<HTMLOptionElement>opts[this.projects[i].accessLevel]).selected = true;
// Department
opts = projectDivs[i].querySelector("select#dept").querySelectorAll("option");
for (var j = 0; j < this.depts.length; j++) {
if (this.depts[j]._id == this.projects[i].department) {
opts[j + 1].selected = true
}
}
//Customer
opts = projectDivs[i].querySelector("select#proCustomer").querySelectorAll("option")
for (var k = 0; k < this.customers.length; k++) {
if (this.customers[k]._id == this.projects[i].customer) {
opts[k + 1].selected = true
}
}
//Official
var asd = (<HTMLSelectElement>projectDivs[i].querySelector("select#proinCharge")).querySelectorAll("option")
for (var l = 0; l < this.users.length; l++) {
/* if (this.users[l]._id == this.projects[i].inCharge) {
asd[l].selected = true
} */
}
}
}
But when I look at the console, this.projects.length is either 0 or 2 (which is the actual number of projects in that meeting). The thing is, when I get it to log 2, the projectDivs[i].querySelector("#access") part errors "Cannot read property 'querySelector' of undefined", which actually makes no sense, since projectDivs are generated like this:
<div class="projectContent" id="projectContent" *ngFor="let project of projects">
and console.log(this.projects.length) returns 2 earlier.
So projects are loaded but the HTML seems to not be loaded properly at that point.
Now for sure i googled this a lot and tried out stuff like jQuery document.ready and checked if document.readyState == complete, but it seems to only apply to the static document and not to the *ngFor generated elements.
So obviously my question in the end is: Is there any way to wait for all *ngFor generated elements or is there just a much easier way of doing this which is wasn't able to spot?
Thanks in advance for all the upcoming answers.
Greetings
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I want to create an json structure with data which will get from an api call. I can generate the structure by using following code. But how can I restructure the code to remove nested call of function and loops.
var temp = {
applications: []
};
api.getApplications(conceptId)
.then((applications) => {
for (var i = 0; i < applications.length; i++) {
(function(indexOfAppArr) {
let applicationId = applications[indexOfAppArr].id;
temp.applications.push({
id: applicationId,
databases: []
});
api.getDbs(conceptId, applicationId)
.then(databases => {
for (var j = 0; j < databases.length; j++) {
(function(indexOfDatabasArr) {
let databaseid = databases[indexOfDatabasArr].id;
temp.applications[indexOfAppArr].databases.push({
id: databaseid,
tabels: []
});
api.
getSchema(conceptId,
applicationId, databaseid).
then(function(schemas) {
for (var k = 0; k < schemas.length; k++) {
(function(indexofschemaarr) {
let schemaid = schemas[indexofschemaarr].id;
api.getTable(conceptId, schemaid)
.then(function(tables) {
console.log(tables);
})
})(k)
}
})
})(j)
}
})
})(i)
}
})
Here is the JSON structure which i want to create.
{
applications:[{
id:'',
databases:[{
id:'',
tabels:[
{
id:'',
columnId:''
}
]
}]
}]
};
If you read a little you'll actually learn how to do it. I personally haven't had the need to learn it yet but it sounded interesting, here is an excellent website that I found for you:
https://javascript.info/promise-chaining
it explains there how to "restructure" the code you are asking by putting it in less words:
loadScript("/article/promise-chaining/one.js").then(function(script1) {
loadScript("/article/promise-chaining/two.js").then(function(script2) {
loadScript("/article/promise-chaining/three.js").then(function(script3) {
// this function has access to variables script1, script2 and script3
one();
two();
three();
});
});
});
I'm sure it only takes less than 30 mts of reading. Best of luck!
I can't add new name and value ff. this given condition:
$.each(names, function (i, name) {
$.get('https://www.example.com/path/' + name, function (data) {
var arrNow = CSVToArray(data, ',');
allArr.push(arrNow);
counter++;
if (counter === names.length) {
for (var j = 0; j < allArr.length; j++) {
for (var k = 1; k < allArr[j].length; k++) {
//console.log(allArr[j][k][0] + ': ' + allArr[j][k][1]);
//var f = moment(allArr[j][k][0]).format('lll');
var f = allArr[j][k][0];
json.push({
"datetime": f
});
if (j == 0) {
if (json[k].datetime === allArr[0][k][0]) {
var newAtt = "water_actual";
var newValue = allArr[0][k][1];
json[k][newAtt] = newValue;
}
}
if (j == 1) {
if (json[k].datetime === allArr[1][k][0]) {
var newAtt = "rainfall_actual";
var newValue = allArr[1][k][1];
json[k][newAtt] = newValue;
}
}if (j == 2) {
if (json[k].datetime == allArr[2][k][0]) {
var newAtt = "forecast_water";
var newValue = allArr[2][k][1];
json[k][newAtt] = newValue;
}
}
}
}
};
});
});
I was able to add a new namewater_actual and its value using if statement. If the datetime from the json object matches to the array value(date and time), I'd like to add it with its specific name as stated above. But I can't seem to make it work.
Here's the fiddle.
If I may provide some general feedback: it's probably good practice to simplify your code to the minimum example that reproduces your problem. Not only can that drastically increase your chances of fixing it yourself, it also increases the odds that you'll get help here.
With that in mind, consider the basic structure of what you're trying here:
var someNames = ["foo", "bar"];
var allTheData = [{
"aardvark": true
}];
$.each(someNames, function (i, name) {
$.get('http://example.com/api/' + name, function (data) {
data.aNewProperty = 'wombat';
allTheData.push(data);
});
});
console.log(allTheData);
Here, $.each iterates through everything in someNames and then proceeds immediately to the console.log statement. For all we know, each individual API call ($.get) could take seconds, or minutes. By this time we've already tried to use the contents of allTheData, which may or may not have been modified.
To avoid this sort of thing in legacy JavaScript we can make use of the callback already provided by $.get:
$.get('http://example.com/api/' + name, function (data) {
data.aNewProperty = 'wombat';
console.log(data);
});
Inside the callback, we know for sure that the API request has already completed (although the above assumes that it succeeded, which is a whole other kettle of fish). This would output the result of each API request as the responses arrive, though not necessarily in the order you'd expect!
JavaScript's asynchronous nature tended to lead in the past to a whole lot of callbacks. With the advent of ES6 we have some more options available to us, especially promises.