JS Break out of function - javascript

I've got a method that looks like this:
return AddedSoftware (software) {
this.softwares.map(function(soft) {
if(soft.id == software) {
return software.name;
}
})
}
So how could I break and return when soft.id == software now it loops through the entire softwares before it returns!

You would use find() instead
return function AddedSoftware (software) {
let res = this.softwares.find(soft => soft.id == software);
// return the software's name if there's a match, or undefined
return res ? res.name : res;
}
This will give you the first object matching your condition. You can then get software.name from that object.
Excerpt from the docs:
The find() method returns a value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

Related

Why i am getting this warning 159:35 warning Expected to return a value at the end of arrow function array-callback-return?

i have this code, i am using find to verify if a element exist:
firstly i was using for like this
for (const file of files) {
if (data.name === proName ) {
exist = true
}
}
this code now i have to use filter, find, contains, map what is the best to solve this problem?
lists.find(data => {
if (
data.name === proName
) {
return data
}
})
but i am getting this warning
159:35 warning Expected to return a value at the end of arrow
function array-callback-return
what happend?
The function doesn't always return. I.e. the else path doesn't have a return in it.
Just do
lists.find(data => data.name === proName)
and it'll infer the data.name === proName as being returned from the lambda, or arrow, function you pass into find.
Otherwise you'll want something like
lists.find(data => {
if (data.name === proName) {
return data
} else {
return null;
});
But returning null isn't what find expects; it expects a boolean.

How to return an element from element.all each

I am trying to return an element from a list of elements and then perform some other actions like click, drag and drop etc. I tried following code but getting error saying nodes.click() not a function
var nodes = vectorpo.yfilesCanvasMain.all(
by.css("g text[fill-opacity='1']")
)
.each(function (eachnode, index) {
eachnode.getText().then(function (text) {
if (text == 'hello world') {
return eachnode;
}
})
});
nodes.click();
As per your problem statement, You are interested in filtering out the array of elements and want to perform some action on filtered list of elements.
As i stated problem and understood correctly then function 'each' is not suitable for this because 'each' function meant for iterating each element of ElementArrayFinder object hence Promise is returned and resolved after calling each elementFinder. 'each' function is used to solve different typr of problems.
So, what is the right approach to address problem you mentioned?
ElementArrayFinder class also provide function 'filter'. This function is meant for filtering out this list of elements. Therefore 'filter' function doesn't return any promise, it returns object of ElementArrayFinder after applying filter condition defined inside it. Refer following code snippet applied for the code you share.
vectorpo.yfilesCanvasMain.all(by.css("g text[fill-opacity='1']")).filter(eachNode, index){
return eachNode.getText().then(function(text){
return text === 'hello world';
});
}).first().click();
Code before first().click() will again return object of ElementArrayFinder which satisfy the condition of element with 'hello world' text. That's why we used first() to get the first element from ElementArrayFinder object.
ElementArrayFinder.each() only can return null, if you stick to use each() to archive your goal, you can do as following:
var found, node;
vectorpo.yfilesCanvasMain.all(
by.css("g text[fill-opacity='1']")
)
.each(function (eachnode, index) {
// if had found the wanted node, end this loop in advance
if (found) return;
eachnode.getText().then(function (text) {
if (text == 'hello world') {
node = eachnode; // assign wanted node to outside variable `node`
found = true; // change flag: found to true
}
})
})
.then(function() {
// the function inside this `then()` will only be executed when above `each()` complete
// if the ouside variable is not null or undefined,
// means find wanted node, then click
if (node) node.click();
});
Even you can archive same goal through each(), but it's more complex than filter(), I'd recommend to use filter()
Write return nodeIndex just after closing the if statement
function getNodeIndex () {
var nodeIndex
var nodes = vectorpo.yfilesCanvasMain.all(by.css("g text[fill-opacity='1']"));
return nodes.each(function (eachNode, index) {
// for (var i = 0; i < noOfNodes.length; i++) { //Somereason if I use for loop the i is always shows as length of the element when I try to print in below if statement
eachNode.getText().then(function (text) {
if (text == 'hello world') {
nodeIndex = index;
console.log("printing index value is " + nodeIndex);
//the nodeIndex is printing correct value
}
return nodeIndex;
});
})
PS : I am using my mobile browser to type this answer so the indentation might not look ok.
After reviewed few other options I tried the following method. I am trying to find the index value of the selected element and want to return that value to my call function. But when I try to output the returned value I am getting null
function getNodeIndex () {
var nodeIndex
var nodes = vectorpo.yfilesCanvasMain.all(by.css("g text[fill-opacity='1']"));
return nodes.each(function (eachNode, index) {
// for (var i = 0; i < noOfNodes.length; i++) { //Somereason if I use for loop the i is always shows as length of the element when I try to print in below if statement
eachNode.getText().then(function (text) {
if (text == 'hello world') {
nodeIndex = index;
console.log("printing index value is " + nodeIndex);
//the nodeIndex is printing correct value
}
})
return nodeIndex;
})
And in another script I used following script
getNodeIndex().then(function(value){
console.log("printing node index after retrieving in function ", value)
})
Here the value is printing as null. Please let me know what am I missing here.
Most of your code is correct, but a wrong on return.
A tiny change as following can fix your problem.
return nodes.each(function (eachNode, index) {
eachNode.getText().then(function (text) {
if (text == 'hello world') {
nodeIndex = index;
console.log("printing index value is " + nodeIndex);
}
});
})
.then(function(){
return nodeIndex;
})
Rather than returning eachnode, we can append eachnode to an ElementFinder[] array and return that. Then we will need to loop through the array to click each one.
// Make a reusable function
async function reusableFunction() {
var nodes = []; // Change 1: Initialize local array
vectorpo.yfilesCanvasMain
.all(by.css("g text[fill-opacity='1']"))
.each(function(eachnode, index) {
eachnode
.getText()
.then(function(text) {
if (text === 'hello world') {
nodes.push(eachnode); // Change 2: add the node to an array
}
})
});
return nodes; // Change 3: return
}
var nodeArray = await reusableFunction(); // Change 4: function call
// Change 5: since we return an array of nodes,
// we need to loop through the array to click each one
nodeArray.forEach(function(node) {
node.click();
});

understanding the return keyword

I have this:
validateForm = () => {
for (let i = 0; i < formInputs.length; i++) {
const inputName = formInputs[i];
if (!this.state.form[inputName].length) {
return false;
}
}
}
which im refactoring in to this:
validateForm2 = () => {
Object.keys(this.state.form).map(input => {
if(!this.state.form[input].length) {
return false
}
return true;
})
}
the first one works, when i fill in my form and the function returns true, if one is empty it returns false.
however i cant seem to quite understand the return keyword to get the same result.
Object.keys says it returns an array but even if I say return Object.keys... or else {return true} I don't seem to get the same result. what am I misunderstanding about return?
You could use Array#every, which uses the return value for a short circuit and for returning the check of all truthy items.
validateForm2 = () =>
Object.keys(this.state.form).every(input => this.state.form[input].length);
Array#map utilizes the return value as new item for each item of the array for a new array, which is dicarded in the given example.
In the first example you have only one (arrow) function which returns either false or undefined.
In the second example you have outer (arrow) function that never returns anything - undefined to the calling code, and the second function that you pass as a parameter to Array.map method. return statements inside the parameter function are not returning anything from the outer function.
validateForm2 = () => {
var emptyItems = Object.keys(this.state.form).filter(input => {
return !this.state.form[input].length;
});
return emptyItems.length == 0;
}
You could modify your function to do what you want it to do.
validateForm2 = () => {
return Object.keys(this.state.form).every(input => {
return this.state.form[input].length;
})
}
You are checking that every property has a length (true). If one of them doesn't, your function returns false.
I think you can avoid using .map in favor of .every() which iterates over every single element and checks whether it has a length greater than zero.
const validateForm = (form) => Object.values(form).every((field) => field.length);
let semiEmptyForm = {
firstField : "",
secondfield : "notEmpty"
};
let nonEmptyForm = {
firstField : "notEmpty",
secondfield : "notEmpty"
};
console.log(validateForm(semiEmptyForm))
console.log(validateForm(nonEmptyForm))

Javascript break/return function within function

I have always been confused about the best way to handle this. The method I have been using in the past works but it seems like there has to be a better way.
Below I have a section of code that I'm wanting to return item for the function getData. Problem is in the example below it's returning for the forEach function not the getData function.
function getData() {
var array = ["element1","element2"];
array.forEach(function (item) {
if (item == "element2") {
return item;
}
});
}
I have been doing something like this to overcome this.
function getData() {
var array = ["element1","element2"];
var returnValue;
array.forEach(function (item) {
if (item == "element2") {
returnValue = item;
}
});
if (returnValue) {
return returnValue;
}
}
Is there a better way to handle this? Seems like those extra 4 lines of code just create confusion and clutter in my code.
You could use Array#some
The some() method tests whether some element in the array passes the test implemented by the provided function.
function getData() {
var array = ["element1","element2"];
var returnValue;
array.some(function (item) {
if (item == "element2") {
returnValue = item;
return true;
}
});
return returnValue;
}
Or, if you use ES6, use Array#find
The find() method returns a value in the array, if an element in the array satisfies the provided testing function. Otherwise undefined is returned.
function getData() {
var array = ["element1","element2"];
return array.find(item => item == "element2");
}
You can readily do this with Array#indexOf:
function getData() {
var array = ["element1","element2"];
var index = array.indexOf("element2");
return index === -1 ? null : array[index];
}
In that case, it works because what you're looking for is an === match for what you have. The more general case is a case for Array#find, which is an ES2015 thing but you can easily shim/polyfill it for ES5 and below:
function getData() {
var array = ["element1","element2"];
return array.find(function (item) {
return item == "element2";
});
}
...which lets you specify the match based on a more complex condition.
You could just use indexOf:
return array[array.indexOf("element2")];
If it doesn't find the value, the index will be -1. And index -1 of any array will be undefined.

Return undefined on Array.map [duplicate]

This question already has answers here:
Why does JavaScript map function return undefined?
(13 answers)
Closed 1 year ago.
I don't want this map to return undefined how can i do that ?
var onCompareSelectedClick = function () {
var talentProfileInfoForAppliedResources = appliedResourcesEntries.map(function(res) {
console.log(res);
if(res.compareSelected == true) {
return data.getTalentProfileInfo(res.RES.RES_ID);
}
});
console.log(talentProfileInfoForAppliedResources);
this.openCompareTPDlg(talentProfileInfoForAppliedResources);
}.bind(this);
Just add else statement inside map method returning needed value, like:
if(res.compareSelected == true) {
return data.getTalentProfileInfo(res.RES.RES_ID);
} else {
return 'default_value';
}
TL;DR
Use the Array.filter method after Array.map to remove undefined elements in the new array.
Expanding on #Bloomca's answer:
As stated in the documentation provided here.
The map() method creates a new array with the results of calling a provided function on every element in this array.
Hence the reason why your new array contains undefined elements is because you are not explicitly calling return within the function on some elements that are called using the provided function. In Javascript, not explicitly calling return will nevertheless return undefined.
For example, in the following method newArray will be set to the logged result:
[ undefined, 2, 3 ]
newArray = [1,2,3].map(function(elem) { if (elem > 1) return elem })
console.log(newArray)
This is why the answer provided above will no longer result in undefined elements within the new array. The conditional will resolve if the condition res.compareSelected == true is not true to the return statement within the else block (note that you could simply remove the true here and simply put res.compareSelected which would be better practice).
Based on your question you may find using the Array.filter method to return an Array without the undefined values. And with only the values on which you have called the function data.getTalentProfileInfo(res.RES.RES_ID).
You could do this in the following manner:
var onCompareSelectedClick = function () {
var arr = appliedResourcesEntries.map(function(res) {
if(res.compareSelected == true) {
return data.getTalentProfileInfo(res.RES.RES_ID);
}
});
var talentProfileInfoForAppliedResources = arr.filter(function(elem) {
return elem;
});
console.log(talentProfileInfoForAppliedResources);
this.openCompareTPDlg(talentProfileInfoForAppliedResources);
}.bind(this);
You can read about the Array.filter method here.

Categories

Resources