Elements won't be pushed to array inside stream() - arrays

When I try to do console.log(recommendedTasks) inside the if condition it works but outside the array remains empty
There is the code I've tried for:
let recommendedTasks = [];
Task.find({}).stream()
.on('data', function(task){
for(let skill of member.skills){
for(let skill2 of task.skills){
if(String(skill) == String(skill2)) recommendedTasks.push(task._id);
}
}
});
console.log(recommendedTasks)

This should be a comment but I dont have those privalages.
It should be because the console.log is being called in a for loop.
The following code should work.
for (i = 0; i < recommendedTasks.length; i++) {
console.log(recommendedTasks[i])
}
Again I wish I could comment. Hope this helps you!

This is happening because you define recommendedTasks outside Task function which triggers at same time as console.log() which takes the first value available [], try this instead.
Task.find({}).stream()
.on('data', function(task){
let recommendedTasks = [];
for(let skill of member.skills){
for(let skill2 of task.skills){
if(String(skill) == String(skill2)) return recommendedTasks.push(task._id);
}
}
});
console.log(recommendedTasks)
Hope it helps.

Related

Iterating through HTMLcollection in React,js

I am having trouble iterating through and HTMLCollection in a React.js component. I have the following function:
shuffleLists = () => {
var elems = document.getElementsByTagName("ul");
console.log(elems)
for (let item of elems) {
console.log(item);
}
}
console.log(elems) prints out an HTMLCollection of ul elements as expected. But the for loop after it doesn't print anything in the console, when I would expect to see each ul element printed in the console. What am I doing wrong?
Edit for clarity:
The key issue here is that the line console.log(item) inside the loop does not output anything into the console in chrome dev tools, and the same applies to other various loop syntaxes as discussed in the answers and comments below.
I also have noticed that there is different lengths being logged from console.log(elems) between different browsers. In chrome I see HTMLCollection[] length: 10 ...
But in Firefox I see
HTMLCollection {length 0} ...
The item in your for loop is actually the key (array index). You need to get the particular element from the elems array by using the syntax elems[item].
Refactoring your code (and changing item to key, just for clarity):
shuffleLists = () => {
var elems = document.getElementsByTagName("ul");
console.log(elems);
for (let key of elems) {
console.log(elems[key]);
}
}
UPDATE: because result of getElementsByTagName() is a NodeList
shuffleLists = () => {
var elems = document.getElementsByTagName("ul");
console.log(elems);
elems.forEach(function(val) {
console.log(val);
})
}
From the MDN Web Docs
Although NodeList is not an Array, it is possible to iterate over it
with forEach(). It can also be converted to a real Array using
Array.from().
However, some older browsers have not implemented NodeList.forEach()
nor Array.from(). This can be circumvented by using
Array.prototype.forEach().
As per the updated requirement of the OP
shuffleLists = () => {
var ulElems = document.getElementsByTagName("ul");
console.log(ulElems);
for(i = 0; i < ulElems.length; i++) {
var liElems = ulElems[i].getElementsByTagName("li");
for(j = 0; j < liElems.length; j++) {
console.log(liElems[j].innerHTML);
}
}
}
document.getElementsByTagName will return an array of elements, in your case array of elements in the page, so you need to have something like the following if you want to have the first ul
shuffleLists = () => {
var elems = document.getElementsByTagName("ul");
console.log(elems)
for (let idx of elems) {
console.log(elems[idx]);
}
}
I would suggest to use document.getElementById() to be more precise about your selected elements
I figured out my problem was that I was calling the shuffleLists function from the parent component in React, prior to the ul and li elements I wanted to iterate through being rendered in the sub-component. The console output for the elems var was confusing as it showed all the lists and list items inside the HTMLCollection.
When I moved the shuffleLists function to the sub-component and called it inside componentDidMount I was able to loop through and console out all the list items as desired.

Array already filled after initialization when i want to sort an array

I would like to sort my array to do this I declared 2 temporary array but the both array are already filled even just after the initialization.
Seems like i got a memory problem
let tmpCheckDeals : any[] = [];
let tmpUncheckDeals: any[] = [];
console.log('Init :' , tmpCheckDeals, tmpUncheckDeals);
this.checkedDeals.forEach(element => {
tmpCheckDeals.push(element);
});
for (let i = 0; i < this.deals.list.length; i++) {
let isInside : boolean = false;
const element = this.deals.list[i];
for (let a = 0; a < this.checkedDeals.length; a++) {
const element1 = this.checkedDeals[a];
if(element == element1)
isInside = true;
}
if(isInside == false) {
console.log('Passe');
tmpUncheckDeals.push(element);
}
isInside = false;
}
Result of my console:
console
As you can see my arrays are already filled
Do you have an idea why i get this error pls ?
Thanks
Your code is working as expected. The console displays the value of the array after the entire code has been executed. If you hover over the "i" icon near the array, it would say "Value below was evaluated just now".
For confirmation, you can check by commenting out the remaining code, except the console log.

Restangular: Empty array using $object

I display my data in a table (smart-table) and everything is working well but in my angular code, when I try to get my "topicList" it's return an empty array. there is my code and thank you in advance.
$scope.topicList= Restangular.all("topic").getList().$object;
for(var k in $scope.topicList) {
console.log($scope.topicList[k]);
if($scope.topicList[k] === "")
{xxxx}
}
Restangular.all('topic').getList().then(function(response) {
$scope.topicList = response;
...
});
After you've assigned the topicList then you can do your bits and pieces.

In Angular, what's the best way to persist data through an asynchronous call?

I have a controller with a for loop that make's HEAD requests for an array of URLs to check if the file exists. When I get the response from the HEAD request, i need the index number from the array that the request was based on.
var allFiles = [], files = [];
allFiles.push({"url":"http://www.example.com/foo","source":"source1"});
allFiles.push({"url":"http://www.example.com/bar","source":"home"});
allFiles.push({"url":"http://www.example.com/wtf","source":"outer space"});
for(var i=0,len=allFiles.length;i<len;i++) {
$http.head(allFiles[i].url).then(function(response) {
files.push(allFiles[VALUE_OF_i_AT_TIME_OF_REQUEST]);
}
}
EDIT:
Because it is an asynchronous call, I cannot use i in place of VALUE_OF_i_AT_TIME_OF_REQUEST. Doing that results in i always being equal to len-1
I guess I can send the index number as data with the request and retrieve it from the response but for some reason that seems hack-ish to me.
Is there a better way?
You can do this with a function closure
for (var i = 0, len = allFiles.length; i < len; i++) {
function sendRequest(index) {
$http.head(allFiles[index].url).then(function (response) {
files.push(allFiles[index]);
});
}
sendRequest(i);
}
I may be oversimplifying this (asynchronous code is still tricky to me), but could you set i to a new local variable j on each loop then reference j instead of i in files.push(allFiles[j]):
var allFiles = [], files = [];
allFiles.push({"url":"http://www.example.com/foo","source":"source1"});
allFiles.push({"url":"http://www.example.com/bar","source":"home"});
allFiles.push({"url":"http://www.example.com/wtf","source":"outer space"});
for(var i = 0, len = allFiles.length; i < len; i++) {
var j = i;
$http.head(allFiles[i].url).then(function(response) {
files.push(allFiles[j]);
}
}
I did something similar to #rob's suggestion and it seems to be doing the trick.
var allFiles = [], files = [];
allFiles.push({"url":"http://www.example.com/foo","source":"source1"});
allFiles.push({"url":"http://www.example.com/bar","source":"home"});
allFiles.push({"url":"http://www.example.com/wtf","source":"outer space"});
for(var i=0,len=allFiles.length;i<len;i++) {
(function(i) {
$http.head(allFiles[i].url).then(function(response) {
files.push(allFiles[i]);
}
})(i);
}

Testing Angular Filter That Returns An Array with Jasmine

So, I'm having issues testing an angular filter that takes an array that has previously been sorted by a group property. It uses a flag property to indicate that the item is the first observation of that group, and then false for subsequent observations.
I'm doing this to have a category header in the UI with an ng-repeat directive.
When I test the filter, the output does not return the array with the flags unless I create new objects for the return array. This is a problem, because it causes an infinite loop when running in a webpage. The code works in the webpage when it just adds a flag property to the input object.
Is there some additional step I should be taking to simulate how angular handles filters so that it outputs the proper array?
This is what my test looks like right now.
describe('IsDifferentGroup', function() {
var list, itemOne, itemTwo, itemThree;
beforeEach(module("App.Filters"));
beforeEach(function () {
list = [];
itemOne = new ListItem();
itemTwo = new ListItem();
itemThree = new ListItem();
itemOne.group = "A";
itemTwo.group = "B";
itemThree.group = "C";
list.push(itemOne);
list.push(itemOne);
list.push(itemOne);
list.push(itemOne);
list.push(itemTwo);
list.push(itemThree);
list.push(itemThree);
list.push(itemThree);
list.push(itemThree);
list.push(itemThree);
});
it('should flag the items true that appear first on the list.', (inject(function (isDifferentGroupFilter) {
expect(list.length).toBe(10);
var result = isDifferentGroupFilter(list);
expect(result[0].isDifferentGroup).toBeTruthy();
expect(result[1].isDifferentGroup).toBeFalsy();
expect(result[4].isDifferentGroup).toBeTruthy();
expect(result[5].isDifferentGroup).toBeTruthy();
expect(result[6].isDifferentGroup).toBeFalsy();
expect(result[9].isDifferentGroup).toBeFalsy();
})));
});
And here is something like the code with the filter:
var IsDifferentGroup = (function () {
function IsDifferentGroup() {
return (function (list) {
var arrayToReturn = [];
var lastGroup = null;
for (var i = 0; i < list.length; i++) {
if (list[i].group != lastGroup) {
list[i].isDifferentGroup = true;
lastAisle = list[i].group;
} else {
list[i].isDifferentGroup = false;
}
arrayToReturn.push(list[i]);
}
return arrayToReturn;
});
}
return IsDifferentGroup;
})();
Thanks!
I figured out my issue.
When I was passing the items into the list, I just pushed a pointer to an item multiple times. I was not passing in unique objects so the flag was being overridden by the following flag in the array(I think). So, I just newed up 10 unique objects using a loop, pushed them into the array and ran it through the filter. And it worked.
I'm not entirely sure my analysis is correct about the override, because itemTwo was not being flagged as unique when it was the only itemTwo in the array. But the test is working as I would expect now so I'm going to stop investigating the issue.

Resources