Sunday, 9 April 2017

Return value from batch async operation

I have a small library that should run a couple of async operations and return an object containing the result of those operations but the interpreter either says the function is not a constructor or when it accepts the constructor, the operation returns an empty object. I think my problem has to do with my variable scoping but maybe it could be worse.

The code itself looks like this

var render = {username: '', available: '', orders: '', frequent: ''},
attachModule = 1;

 function OnIndexLoad (username) {

this.endRes = function (username) {
    render.username = username;
    console.log(render)
    return render;
};

this.init = function (username, current) {
    var utilMap =    {

    1: function (index) {
        http.get({port: '1717', path: '/admin/', headers: {Accept: 'text/html'}}, function(res) {
        var temp = ''
        res.setEncoding('utf8');

        res.on('data', function (chunk) {
            temp += chunk;
        }).on('end', function() {
    // add result of async operation
            render.available = temp
            index++
        })

    }).on('error', function(e) {
            console.log(e)
        });
    },

    2: function(index) {
        http.get('http://localhost:1717/admin/page=20',  function(res) {

        var temp = ''
        res.setEncoding('utf8');

        res.on('data', function (chunk) {
            temp += chunk;
        }).on('end', function() {
    // add result of async operation
            render.orders = temp;
            index++
        })
    }).on('error', function(e) {
            console.log(e)
        });
    },

    3: function(index) {
        ordersModel.find({}, , function (err, orders) {
        if (err) throw err;

// ignore this whole bit but look out for the function's last line
        var hashMap = [], returnArr = [];

        orders.forEach(function (order) {
            hashMap.push(order.toObject()['food'].split(","));
        })

        hashMap.reduce(function(a, b) {
            return a.concat(b)
        }, []).forEach(function(item) {

            if ((k = returnArr.findIndex(function(elem) {
                return elem[0] == item;
            })) != -1) {
                returnArr[k][1]++;
            }
            else returnArr.push([item, 1]);
        })

        hashMap = [], returnArr = returnArr.sort(function(a, b) {
            return b[1] - a[1];
        }).slice(0, 5).forEach(function(elem) {
            hashMap.push({name: elem[0], counter: elem[1]})
        });
    // add result of async operation
        render.frequent = component("frequent", hashMap); // here
        index++;
    })
    }
    }; // close util map

// the important part
    var itemsToReturn = Object.keys(render).filter(e => e != 'username');
    utilMap[current](current);

    if (attachModule < itemsToReturn.length) {
            this.init(current, username) // does not recurse and incrementally perform async ops
        }
        else this.endRes(username);
}

this.init(attachModule, username)
}

exports = OnIndexLoad 

Then, in a middleware from the calling script i.e the index.js requiring this library, I have,

var onIndexLoad = require("./lib/index-load");
new onIndexLoad(req.session.username);

I thought calling it that way will expose the loaded object for me--something like this

{key1: resultOfOperation1, key2: resultOfOperation2, key3: resultOfOperation3}

But calling it that way only exposes errors. How do I call the endRes only and only when the render object is ready to be exported?



via Mmayboy

No comments:

Post a Comment