JSHint won't allow forEach in a for loop - javascript

I keep getting EsLint errors for having forEach in my loop. How can I fix the following code:
for (var i = 0; i < this.m_V.length; ++i) {
var o = this.m_V[i];
var node = o.m_Data.GetCurr(this.m_C);
if (node && node.m_datae.length) {
for (var j = 0; j < node.m_datae.length; ++j)
var dataelement = node.m_datae[j].m_dataat
AreaId.forEach(function(area) {
dataelement.forEach(function(value) {
if (area === value.m_V) {
if (vo.m_p) {
var a = v.m_p.map;
....
}
}
}
}, this);
}, this);
}
}
}
How can I move the forEach out of the code? I tried to move the forEach out but then it didn't know what my variables node and 'o' were.

Related

How do i get the specific values from json data in React

I am getting an error in console while i am trying to get a specific value from json data. This is the error:
'Uncaught TypeError: Cannot read property 'processen_id' of undefined'
Here is my code:
$.get("/getProces", function (data) {
if (data.error) {
} else {
for (var i = 0; i <= data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
}
})
}
This is what i get when i log (data):
You have a mistake in your code in the for loop
<= instead of <
$.get("/getProces", function (data) {
if (data.error) {
} else {
for (var i = 0; i < data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
}
})
}
The error message means that obj is undefined. That means, that data.message[i] gets an undefined value. The problem is the loop. You get an i that is larger then the array. Change <= to <:
for (var i = 0; i < data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
index out of range: for (var i = 0; i <= data.message.length; i++) { should be for (var i = 0; i < data.message.length; i++) { instead.
you can also optimize your code in this way:
$
.get("/getProces")
.then((res) => res.error ? Promise.reject(res) : Promise.resolve(res))
.then((data) => {
for (var i = 0; i < data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
})

Javascript- how do you convert this foreach loop to a regular for-loop?

This nested loop is running really slow in my app so I'm trying to change it to use regular for-loops instead of foreach. I'm a little confused on the find() part. Can someone help me convert this nested loop so that it doesn't use any foreach loops? thanks.
var filters = [];
if (selectionTagFilters.length > 0) {
for (var i = 0; i < selectionTagFilters.length; i++) {
filterTree.forEach(function find(tag) {
if (tag.tagCategoryId == selectionTagFilters[i].tag.tagCategoryId) {
tag.tags.forEach(function find(tag) {
if (tag.tagId == selectionTagFilters[i].tag.tagId) {
filters.push({ tagHeader: tag.tagHeader, tagId: tag.tagId, tagCategoryId: tag.tagCategoryId });
}
});
}
});
}
}
var filters = [],
selectionTagFilterItem = null,
filterTreeItem = null,
tagItem = null;
for(var i = 0, ii = selectionTagFilters.length; i < ii; i++) {
selectionTagFilterItem = selectionTagFilters[i];
for(var fti, ftii = filterTree.length; fti < ftii; fti++) {
filterTreeItem = filterTree[fti];
if (filterTreeItem.tagCategoryId != selectionTagFilterItem.tag.tagCategoryId) continue;
for(var ti = 0, tii = filterTreeItem.tags.length; ti < tii; ti++) {
tagItem = filterTreeItem.tags[ti];
if (tagItem.tagId != selectionTagFilterItem.tag.tagId) continue;
filters.push({ tagHeader: tagItem.tagHeader, tagId: tagItem.tagId, tagCategoryId: tagItem.tagCategoryId });
}
}
}

Repeat function in javascript

Could you please tell me how to make from this 4 functions just 1. Cause they all do one thing, with just one parameter changing all the time.
Also, I need to take the value of each time the function is running and put it into a new variable so I can after calculate it.
function getValue(age)
{
for (var i = 0; i < document.getElementsByName('age').length; i++)
{
if (document.getElementsByName('age')[i].checked)
{
return document.getElementsByName('age')[i].value;
}
}
}
function getBmiValue()
{
for (var i = 0; i < document.getElementsByName('bmi').length; i++)
{
if (document.getElementsByName('bmi')[i].checked)
{
return document.getElementsByName('bmi')[i].value;
}
}
}
function getFamValue()
{
for (var i = 0; i < document.getElementsByName('fam').length; i++)
{
if (document.getElementsByName('fam')[i].checked)
{
return document.getElementsByName('fam')[i].value;
}
}
}
function getDietValue()
{
for (var i = 0; i < document.getElementsByName('diet').length; i++)
{
if (document.getElementsByName('diet')[i].checked)
{
return document.getElementsByName('diet')[i].value;
}
}
}
function getValueByElementName(element_name)
{
for (var i = 0; i < document.getElementsByName(element_name).length; i++)
{
if (document.getElementsByName(element_name)[i].checked)
{
return document.getElementsByName(element_name)[i].value;
}
}
}
Or a little bit optimization:
function getValueByElementName(element_name)
{
var elements = document.getElementsByName(element_name);
for (var i = 0; i < elements.length; i++)
{
if (elements[i].checked)
return elements[i].value;
}
}
function getValue(tagname)
{
for (var i = 0; i < document.getElementsByName(tagname).length; i++)
{
if (document.getElementsByName(tagname)[i].checked)
{
return document.getElementsByName(tagname)[i].value;
}
}
}
Pass your element name as a variable in this function and call it.
Here is an example of what you can do:
function getValue(key) {
// get this once, not on each loop iteration
var elem = document.getElementsByName(key);
// cache the length too, so not to calculate it on each loop iteration
for (var i = 0, len = elem.length; i < len; i++) {
if (elem[i].checked) {
return elem[i].value;
// this will exit the function when it finds the FIRST one.
// Is that what you want?
}
}
}
// you can call above function like this:
getValue('age');
getValue('bmi');
getValue('fam');
getValue('diet');

JavaScript continue label scope

Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
continue nextVehicle;
});
}
}
}
};
The code above does not work. I have a feeling this is to do with scope, I can't reach the nextVehicle label from inside the oldVehicle.getPosition method. How can I get around this?
Separate the matching logic from the update logic.
Map.prototype.updateMap = function (vehicles) {
// Only need to look up array lengths once
var vehiclesLength = vehicles.length,
oldVehiclesLength = this.oldVehicles.length;
for (var i = 0; i < vehiclesLength; i++) {
var vehicle = vehicles[i];
var oldVehicle = null;
// Find oldVehicle
for (var j = 0; j < oldVehiclesLength; j++) {
if (vehicle.registration == oldVehicle[j].registration) {
oldVehicle = oldVehicles[j];
break;
}
}
// Check for update if found
if (oldVehicle){
// Create closure for async callbacks
(function(oldV, lat,lng){
oldV.getPosition(function(latLng) {
if (lat != oldV.lat) {
var newPos = new plugin.google.maps.LatLng(lat,lng);
oldV.setPosition(newPos);
}
});
})(oldVehicle, vehicle.latitude, vehicle.longitude);
}
}
};
Just move the continue nextVehicle; line from inside the callback to immediately following the call to oldVehicle.getPosition(...):
Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
});
continue nextVehicle;
}
}
}
};
This assumes the call to getPosition is a synchronous operation.
Edit:
Now if getPosition is asynchronous, you will need to use an asynchronous loop:
Something along this line might do the trick:
Map.prototype.updateMap = function (vehicles) {
var i = 0, j = -1, self = this;
var updatePosition = function() {
j++;
if (j == self.oldVehicles.length) {
j = 0;
i++;
}
if (i === vehicles.length) {
return; // We're done
}
var vehicle = vehicles[i];
var oldVehicle = self.oldVehicles[j];
if (vehicle.registration !== oldVehicle.registration) {
updatePosition();
}
else {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
updatePosition();
}
});
}
};
updatePosition();
};

An interval that calls a function inside an object, which also calls a function inside that object

function airEngineJS (canvasArg, properties) {
this.canvas = (canvasArg == "undefined")? trace("Failed to set up canvas for airEngineJS") : canvasArg;
this.cameras = [];
this.displayObjects = [];
this.hudDisplayObjects = [];
this.fps = (properties == "undefined" || properties.fps == "undefined")? 30 : properties.fps;
if (properties == "undefined" || properties.autoinit == "undefined" || properties.autoinit == true){
this.keyboard = new keyboardJS();
this.keyboard.init();
this.cameras.push(new airCameraJS(this));
}
this.enterframe = setInterval(this.intervalCaller, 1000/this.fps);
trace("A new airEngineJS has been created");
}
airEngineJS.prototype = {
intervalCaller : function () {
this.mainLoop();
},
logic : function () {
for (var i = 0; i < this.displayObjects.length; ++i){
this.displayObjects[i].logic();
}
for (var j = 0; j < this.cameras.length; ++j){
this.cameras[j].logic();
}
},
render : function () {
for (var i = 0; i < this.cameras.length; ++i){
for (var j = 0; j < this.displayObjects.length; ++j){
this.displayObjects[j].renderOn(this.cameras[i]);
}
}
for (var i = 0; i < this.hudDisplayObjects.length; ++i){
this.hudDisplayObjects[i].renderOn(this.canvas);
}
},
mainLoop : function () {
this.logic();
this.render();
}
}
The interval [this.enterframe = setInterval(this.intervalCaller, 1000/this.fps);] calls correctly (this.intervalCaller), but this tries to call (this.mainLoop()) in the DOM.
Any suggestions about how should I do it? :(
You can close over the actual function call like this:
var self = this;
this.enterframe = setInterval(function() {
self.intervalCaller();
}, 1000/this.fps);
It first creates a reference to the new instance which is then used inside the closure passed to setInterval.

Categories