Home > Enterprise >  D3 function called inside another function always returns undefined
D3 function called inside another function always returns undefined

Time:10-26

Sorry for what may turn out to be an exceedingly naive question, but I'm quite new to D3 and I've been struggling with this issue for a couple of days now, trying to troubleshoot it in a number of different ways.

Full disclosure: I'm using D3 v7.

I've been working on a simple dashboard for my company listing order data, which should ultimately use two different CSV files. I've managed the visualization based on the first file, and I've managed to apparently load and produce an object based on the other CSV file. The problem is, whenever I use the function which transforms this object based on the second CSV, it always returns undefined.

I know that the data is loaded---I even loaded both CSVs at the beginning using Promise.all---still it didn't solve the issue. The code I share below might look a bit unhinged, since first of all I've used a lot of console.logs to detect what's happening where, and second---I've tried to adjust it in many different ways and frankly don't even immediately remember the reasons for all the adjustments.

Now, at this point I wouldn't be surprised if it has all been caused by some sort of typo which is somehow obscured by my selective blindness. I'd anyway be grateful if you could comment on how I could proceed in troubleshooting this code.

Now---here's the two functions which seem to be clashing. The addOrderData takes the SKU of a product and the object which contains the order data, filters the orders based on the SKU, groups them according to date and sums them using rollup, before returning the resulting object. I can see that all the actions work when the function is carried out, except perhaps for the return statement:

    function addOrderData(product_sku, datanew) {
        datanew = datanew.filter(d => d['Variant SKU'] == product_sku)
        seriesnew = datanew.map(d => ({
            name: d['Product Title'],
            sku: d['Variant SKU'],
            count: d['Line Item quantity'],
            fulfilled: parser(d['Fulfillment at'].substring(0, 10)),
            created: parser(d['Created at'].substring(0, 10)),
            paid: parser(d['Paid at'].substring(0, 10))
        }))
        console.log('ORDER DATA HERE A-COMIN!');
        console.log(seriesnew);
        let ordersByDate = d3.group(seriesnew, d => d.fulfilled)
            // .rollup(v => {
            //     total: d3.sum(v, d => d.count)
            // })
        console.log(ordersByDate)
        let ordersByDateRolled = d3.rollup(seriesnew, v => d3.sum(v, d => d.count), d => d.fulfilled)
        console.log('Bleeemmm!')
        console.log(typeof(ordersByDateRolled))
        console.log('Bloommm!')
        return ordersByDateRolled;
    }

Now, the updateSelection function reloads the objects (I know it's very inefficient, but while trying to troubleshoot everything I kind of wanted to have everything everywhere), draws the original chart according to the SKU selected, and is supposed to draw the other chart based on the order data:

    function updateSelection() {
        d3.select('#article_name_drop').on('change', function() {
            d3.select(container).html(null);
                Promise.all([
                    load_data(),
                    d3.csv('dk_orders.csv')
                ])
                .then(data => {
                    bws = data[0]
                    orders = data[1]
                    populateDropdown(bws)
                    resetData();
                    let valuezz = this.value;
                    const sku = valuezz.split(' ')[0]
                    console.log(valuezz);
                    new_data = bws
                    new_data.series = bws.series.filter(d => d['name'] == valuezz)
                    console.log(new_data)
                    drawChart(container, new_data)
                    console.log('ADDING')
                    let summedOrderData;
                    console.log(sku);
                    console.log(orders)
                    summedOrderData = addOrderData(sku, orders).then(
                        console.log(summedOrderData),
                        console.log('ADDED'),
                        // console.log(summedOrderData)
                        drawSubChart(subcontainer, summedOrderData)
                    );
            })
        })
    }

The problem is---addOrderData called here consistently returns undefined, even though I can see in the console that the function is running correctly. You can see here I've tried to troubleshoot this using the .then() statement, but still---the 'then' just proceeds to act on an undefined object, which causes an error with the other functions.

Sorry for all the mess with the code, I usually program in Python and JS in general is quite new to me. I'd be grateful for any hints of what to do.

Cheers, Raf

CodePudding user response:

The following passage is your issue, because you are using drawSubChart with summerOrderData before its allocated to any value

summedOrderData = addOrderData(sku, orders).then(
                    console.log(summedOrderData),
                    console.log('ADDED'),
                    // console.log(summedOrderData)
                    drawSubChart(subcontainer, summedOrderData)
                );

Using then with addOrderData will also don't do anything because addOrderData is not returning a Promise.

Try the following:

1 - allocate summerOrderData to the result of addOrderData

2 - use summerOrderData with drawSubChart

summedOrderData = addOrderData(sku, orders);
drawSubChart(subcontainer, summedOrderData);
  • Related