javascriptnode.jssveltesapper

Combine arrays in map function


I have an issue, or at least I'm not having the solution.

I'm getting some API calls via a map and I can console.log all results which is great, but the problem is that I want to combine all the results in one array.

var alpha = ['a', 'b', 'c', 'd', 'e'];

alpha.map(alpha => {
 fetch(`https://myurl.com/api/members/page?prefix=${alpha}`)
 .then(res => res.json())
 .then(data => matches.push)
 .then(() => console.log(matches))
})

I guess I have to do some sort of await or something?

My response from the API looks like this:

{"list_complete":true,"keys":
    [
        {
            "username": "name.com",
            "uuid": "-47c9-88b6-2474090c7927",
            "user_type": 1,
            "subscribed": "false",
            "lastLogin": 1611066809086,
            "profile": {
                "name": "Name Lastname",
                "email": "name.com",
                "uuid": "3e92f458-6331-2-88b6-2474090c7927",
                "address": "",
                "history": [
                    {
                        "titleId": "5fac58f764e6710017411e79",
                        "posterUrl": "url.jpg",
                        "displayName": "Guns N ´ Roses - Appetite for Democracy",
                        "t": 0,
                        "d": 8492.2
                    },
                    {
                        "titleId": "5f7eadb3963c170017a919f3",
                        "posterUrl": "url.jpg",
                        "displayName": "Frank Zappa - Apostrophe Overnite Sensation (Classic Albums)",
                        "t": 7.728575,
                        "d": 2974.9
                    },
                    {
                        "titleId": "5e4463a395c832405e7effc0",
                        "posterUrl": "url.jpg",
                        "displayName": "Bob Marley - Uprising Live!",
                        "t": 3285.406821,
                        "d": 6807.7
                    },
                    {
                        "titleId": "5f80c6d0045fdf0017735019",
                        "posterUrl": "url.jpg",
                        "displayName": "Van Morrison - In Concert",
                        "t": 3610.529879,
                        "d": 4558.29
                    },
                    {
                        "titleId": "5fa85aba9c4a1900177e5cf9",
                        "posterUrl": "url.jpg",
                        "displayName": "Iron Maiden - En Vivo!",
                        "t": 2522.988949,
                        "d": 3380.5
                    },
                    {
                        "titleId": "5f719cb75d994e0017b429c5",
                        "posterUrl": "url.jpg",
                        "displayName": "Placebo - Placebo Live At The O2 Brixton Academy",
                        "t": 1426.589863,
                        "d": 5061.89
                    },
                    {
                        "titleId": "5fb3fd1731be640017c2f878",
                        "posterUrl": "https://slam-assets.s3.eu-north-1.amazonaws.com/staging/5fb3fd1731be640017c2f878/cover/1606214166013_nirvanastaende.jpg",
                        "displayName": "Nirvana - Nevermind (Classic Albums)",
                        "t": 0,
                        "d": 2948.69
                    }
                ],
                "favourites": [
                    "5f9039ed1279d600170378c2",
                    "5facf94364e6710017411e7d",
                    "5e4463a395c832405e7effc0"
                ]
            },
            "subscription": null
        }
    ]
}

And the data I want to collect is in a array called history under each user.


Solution

  • To my understanding you are getting data as a result of your fetch, and you will get as many returns of data for the elements of the alpha array. You would like to combine the results of your history object, from the data, into a single one-dimensional array. That means that your target array looks like:

    histories = [{},{},{} ... ]
    

    Where each object {} is a history element.

    In order to perform the required operation we need to access the keys elements first and iterate through all of those, retrieving the history contents from each of them. However, you mentioned history may or may not exist for a user, thus we need to check for its existance .

    So, summing up:

    We may perform the first action by using a forEach() method on data.keys, whilst a simple if (element.profile.history) to check for the presence of history:

    var alpha = ['a', 'b', 'c', 'd', 'e'];
    const histories = [];
    
    alpha.map(alpha => {
        fetch(`https://myurl.com/api/members/page?prefix=${alpha}`)
            .then(res => res.json())
            .then(data => data.keys.forEach(function (e) { //Iterate through the keys
                if (e.profile.history) { //If history is present
                    histories.push(...e.profile.history); //Pushing to array with spread sytnax
                }
            })
            )
    })
    

    In order to have one single array with all the history items, we made use of the spread ... syntax, you can read more about it here

    So the output of:

    console.log(histories)
    

    Will then yield:

    [
      {
        titleId: '5fac58f764e6710017411e79',
        posterUrl: 'url.jpg',
        displayName: 'Guns N ´ Roses - Appetite for Democracy',
        t: 0,
        d: 8492.2
      },
      {
        titleId: '5f7eadb3963c170017a919f3',
        posterUrl: 'url.jpg',
        displayName: 'Frank Zappa - Apostrophe Overnite Sensation (Classic Albums)',
        t: 7.728575,
        d: 2974.9
      },
      {
        titleId: '5e4463a395c832405e7effc0',
        posterUrl: 'url.jpg',
        displayName: 'Bob Marley - Uprising Live!',
        t: 3285.406821,
        d: 6807.7
      },
    ...
    ]