I have a bizarro issue which I just ran into ... when passed an array of objects, the for..of iterator has no problem iterating over the objects and giving me the "name" property of each. However, array.forEach completely fails to iterate.
The main function is found in Database.ts:
import { ITableDefinition } from "./Table";
export function Database(...tables: ITableDefinition<any>[]) {
const names: string[] = [];
for (const table of tables) {
names.push(table.name);
}
return {
tables,
tableNames: tables.forEach((table) => table.name),
tableNamesWithForOf: names,
};
}
As you can see the function reflexively passes the array of tables it receives but also passes the name property of each table and it does it twice. Once using forEach and once using for..of.
When running the following Jest tests, 2 of the 3 pass but the forEach test fails:
describe("Trouble with iterables => ", () => {
// db.tables is received as an array
it("tables property is an array", () => {
const db = Database(Table(Song), Table(Playlist));
expect(Array.isArray(db.tables)).toBe(true);
expect(typeof db.tables[0]).toBe("object");
});
// for..of iterates over the array correctly and extracts the "name" prop
it("for ... of returns the names of the tables correctly", () => {
const db = Database(Table(Song), Table(Playlist));
expect(db.tableNamesWithForOf).toHaveLength(2);
expect(db.tableNamesWithForOf).toContain("Song");
expect(db.tableNamesWithForOf).toContain("Playlist");
});
// shockingly, forEach doesn't iterate at all and returns `undefined`!
it("forEach returns the names of the tables correctly", () => {
const db = Database(Table(Song), Table(Playlist));
expect(db.tableNames).toHaveLength(2);
expect(db.tableNames).toContain("Song");
expect(db.tableNames).toContain("Playlist");
});
});
My mind is blown but I'd love to hear from you if you can make some sense of it.
Git Repo - all code and tests
GitPod Container ... new to GitPod, hopefully the link works (super convenient)
Note: I tagged as both javascript and typescript but i doubt this has to with transpiling so if folks think I should take off the TS tag let me know and I'll do so.
forEach in tables.forEach((table) => table.name) doesn't return anything i.e. returns undefined, you can use .map instead
Related
I have the following code:
const getNFTs = async (address: string) => {
... // hidden for brevity
//Nested code
const promises = Array.from({length: output.toNumber()}).map() => {
... // hidden for brevity
}
const promiseArray = await Promise.all(promises); //returns object
const imageArray = Object.values(promiseArray); //converts to array
}
If I was to console.log imageArray I am given an array like this:
['https://imagepath.com/image1.png','https://imagepath.com/image2.png','https://imagepath.com/image3.png',]
I want to use imageArray to map through the array and render a grid of images on the UI. But when I try to map through this, I get an error that imageArray is not defined most likely due to scoping issues.
Do I write the map function (with the required HTML/JSX markup) within the getNFTs async function? Or is there a better way to access the array to generate the list of images on the UI?
promiseArray should already be an array of image URLs, Object.values will effectively yield the same value. Recall that an Array is just a special object of associative key-value pairs, i.e. the keys are the array indices and the values are the stored array values. If the returned resolved value isn't the image URLs then you can likely "unpack" them higher up in the Promise chain when processing the asynchronous requests.
You can save this array to the outer scope by adding some React state to hold this array value, and enqueue a state update to save it and trigger a rerender.
Example:
const [imageArray, setImageArray] = React.useState([]);
...
const getNFTs = async (address: string) => {
... // hidden for brevity
//Nested code
const promises = Array.from({ length: output.toNumber() }).map() => {
... // hidden for brevity
}
const imageArray = await Promise.all(promises);
setImageArray(imageArray);
};
...
Later you can reference the imageArray state and render it as necessary.
imageArray.map(.....)
Hello so I am creating a filter search and I 'm trying to collect all the key (tags) that the user press, inside an array, however every time that a new value is push it does override the entire array. So I tried a couple of things, like spread syntax, concat, etc. But with no luck.
So my action looks like this:
const setCurrentFilters = async (context, payload) => {
if (payload) {
context.commit('setCurrentFilter');
}
}
My state
state:{
filters: JSON.parse(sessionStorage.getItem('currentFilters') || '[]'),
}
The mutation
setCurrentFilter(state, payload) {
state.filters.push(payload);
sessionStorage.setItem('currentFilters', JSON.stringify(payload));
}
And my getter
currentFilters(state) {
return state.filters;
},
Thank you in advance for any help : )
This is simply because you set const filters = []; which means that the next condition if (filters.length) will always return false (as you just created this array) and therefore the else statement will execute.
in the else statement you basically push the new payload to the empty array you just initialized - which makes your array always hold only the new value
i believe that you just need to remove the const filters = []; line, and access the filters property that exists in your state
I want to access data inside a list, but I cannot access it using the square brackets []. The getTalonPaie is a function that call the get method from the HttpClient service and it returns me an observable containing multiple values. The problem is when I was to put it in my array, it is not returning me multiples arrays but one weird empty list with data in it.
onSubmit(): void {
this.listeTalonPaie = Array<number>(1);
const test = [1, 2, 3];
this.listeIndividus = this.indS.listeIndividu;
this.listeIndividus.forEach(ind => {
// The function below is returning me an observable (from httpClient.get()) containing
// multiple objects and I want to add them in my array. I used the push method because
// I need a dynamic array since the number of objects returned by the observable is not
// static.
this.rcs.getTalonPaie(ind.id)
.subscribe( data => {
this.listeTalonPaie.push(data.heures);
test2.push(data.heures);
});
});
// The output is [empty] (i)
// 1: 25
// 2: 40
// 3: 36
// length: 4
// __proto__ : Array(0)
console.log('listeTalonPaie ', this.listeTalonPaie);
// The output is [null]
console.log('listeTalonPaie ', JSON.stringify(this.listeTalonPaie));
// The output is undefined
console.log('Un element ', this.listeTalonPaie[0]);
// The output is (3) [1, 2, 3]
console.log('test ', test);
}
I'm not sure if it's the right way to do it. So if you think there is a better method tell me.
So data is an array and you're pushing that array into this.listeTalonPaie (also an array), so you end up with a nested array [[1,2,3]].
Not sure what your intent is but you might want to use concat or spread instead of push.
this.listeTalonPaie = [...this.listeTalonPaie, ...data.heures];
my console.log() was printing me undefined data.
The subscribe method is asynchronous so console.log is running before your data callback gets invoked. Here's a tiny simulation of it:
// mock subscribe implementation
const subscribe = (callback) => {
// wait half a second then invoke callback with some data
setTimeout(() => callback([1,2,3]), 500);
}
let result = [];
subscribe(data => {
result = [...data];
console.log('1:', result);
});
console.log('2:', result); // <-- called before 1
The problem is with the subscription syntax. I think you should make a new function below and provide it to the subscription.
this.rcs.getTalonPaie(ind.id)
.subscribe( data => {
this.listeTalonPaie.push(data.heures);
this.logDataList(data)
});
});
logDataList(data: any) { console.log(data) };
If it possible you can pull data in ngOnInit and then you have an easy way to get data from your variable when you run onSubmit function
I found that there was no actual problem. In fact, my list works, but my console.log() was printing me undefined data. If someone could explain me why I get undefined data in the console instead of the real value I would be happy !
I have a function:
// helper.js
export const someFunction = (complexObj1, complexObj2) => {
const someObj = complexObj1.generateAnObject();
const objList = someObj.generateListOfObjects();
for (const obj of objList) {
obj.performAction();
}
};
As you can see, it's a pretty much a void function that performs a bunch of tasks. The "complexObj1" and "complexObj2" objects and the functions it has attached to them are all generated from an API I am using.
Things I would like to test:
parameters complexObj1 and complexObj2 are valid objects
someObj within fucntion is a valid object with maybe checking a certain property exists
objList returns a valid list
each obj in the loop is a valid object
What is the right way to test a function like this? I've looked into Jest mocking but I'm not sure if this fits my scenario.
test("Test someFunction", () => {
// not sure what to do here or what to mock etc
});
Can I not test functions like this?
If anyone can give me an example of how to test this or even just point me in the right direction I would be thankful. I really want to learn how to do this.
Looks like the function accepts an object, calls a function on that object to generate a different object, calls a function on that object to generate an array, then calls a function on each object in the array.
Since it only knows about what is passed to it, you can pass appropriate mock data and use mock functions to confirm that it is working properly:
const someFunction = (complexObj1) => {
const someObj = complexObj1.generateAnObject();
const objList = someObj.generateListOfObjects();
for (const obj of objList) {
obj.performAction();
}
};
test('someFunction', () => {
const objList = [
{ performAction: jest.fn() },
{ performAction: jest.fn() }
];
const obj = {
generateAnObject: () => ({
generateListOfObjects: () => objList
})
};
someFunction(obj);
expect(objList[0].performAction).toHaveBeenCalled(); // Success!
expect(objList[1].performAction).toHaveBeenCalled(); // Success!
})
I have the following code:
ngOnInit(): void
{
const source = this.categoryService.getCategories();
console.log(source instanceof Observable);
const example = source.map((categor) => categor.map((categories) => {
const links = this.categoryService.countCategoryLinks(categories.id);
const aff = example.merge(links).subscribe(linke => console.log(linke));
return categories.id
}));
}
where getCategories() returns an observable.
On each item of this Observable, I get categories.id field to run another method called countCategoryLinks(categories.id) that also returns an Observable().
My problem is that : I only have 3 categories (ok), the countCategoryLinks() returns 3 items (ok) but the code above shows an infinite loop in the console.
Both methods started "manually" for testing purpose do not show any loop.
The problem really comes from the code above.
Any idea ?
Thanks in advance and Regards
example.merge(links) <= you are using an observable created by the map callback in the map callback which would cause recursion (ie. loop back into itself). This is where it pays to use proper indention as it is easier to see.
ngOnInit(): void {
const source = this.categoryService.getCategories();
console.log(source instanceof Observable);
const example = source.map((categor) => categor.map((categories) => {
const links = this.categoryService.countCategoryLinks(categories.id);
// this line is the issue. You are using variable example which is being created by the callback this line of code is in
const aff = example.merge(links).subscribe(linke => console.log(linke));
return categories.id
}));
}
I am thinking maybe you did not mean to still be inside of map at this point?