0

I´m using express/ node, mysql and bluebird.

I´m performing three async database queries using Promise.all(). After these were performed I have to do some calculation.

If I do this I can call the function getDateRange() successfully, but this leads me to the problem, that I have trouble doing some error handling.

return Promise.all([departmentDatabase.getVacation(departmentID), departmentDatabase.countUser(departmentID), departmentDatabase.blockedDaysOfResponsible(departmentID)])
            .then(departmentData =>  [departmentData, departmentData[0].map(entry => this.getDateRange(new Date(entry.dateFrom), new Date(entry.dateTo)))] )
            .spread(function(departmentData, dateRange){

                var mergedDateRange = [].concat.apply([], dateRange);
                var counts = {};
                mergedDateRange.forEach(function(x) { counts[x] = (counts[x] || 0)+1; });       //Zähle doppelt vorkommende Daten

                var departmentMinStock = departmentData[0][0].departmentMinStock;
                var blockedDays = [];

                for (var p in counts) {
                    if( counts.hasOwnProperty(p) ) {
                        if( (parseInt(departmentData[1][0].amount) - parseInt(counts[p])) <= parseInt(departmentMinStock)) {
                            blockedDays.push(p);
                        }
                    }
                }
                return [{"vacationRequest": departmentData[0], "blockedDays": blockedDays}, departmentData[2]];
            })
            .catch(err => {
                // ...do something with it...
                // If you want to propagate it:
                return Promise.reject(err);
                // Or you can do:
                // throw err;
            });

In case that departmentData is undefined, which can happen quit often, I have no real option (that I know) to stop all following .then() calls and just return an empty array. I could return an empty array, but then I would have to do the check in every .then() is have.

So I thought, because I use Promise.all() I don´t really have following async operation, therefore I could just do all my logic inside the callback of .all().

But if I try to do it this way:

 return Promise.all([departmentDatabase.getVacation(departmentID), departmentDatabase.countUser(departmentID), departmentDatabase.blockedDaysOfResponsible(departmentID)])
            .then(function(data){

                var d = [];
                for(var i = 0; data[0].length > i; i++){
                    //console.log(this.getDateRange(new Date(data[0][0].dateFrom), new Date(data[0][0].dateTo)));
                    //console.log(data[0][i].dateFrom);
                    //console.log(data[0][i].dateTo);
                    var x = this.getDateRange(data[0][i].dateFrom, data[0][i].dateTo);
                    console.log(x);
                   // d.push(this.getDateRange(new Date(data[0][0].dateFrom), new Date(data[0][0].dateTo)));
                }

                return 1;
            })

It results in an error TypeError: Cannot read property 'getDateRange' of undefined. But console.log(data[0][i].dateFrom); has a value I have checked that.

This is my getDateRange function:

 getDateRange(startDate, stopDate) {
        var dateArray = [];
        var currentDate = moment(startDate);
        while (currentDate <= stopDate) {
            dateArray.push(moment(currentDate).format('YYYY-MM-DD'))
            currentDate = moment(currentDate).add(1, 'days');
        }

        return dateArray;
    }

Can someone exlpain me why this is happening? And best would be an example on how to do it right in this case?

BayLife
  • 367
  • 1
  • 13
  • Error message says `this` has no property `getDateRange()` can you confirm that class has this method? – Sohaib Farooqi Nov 14 '16 at 07:46
  • @SohaibFarooqi yes, the class does exist and is called if I do it outside the `.all()` callback! – BayLife Nov 14 '16 at 07:51
  • you need to understand what `this` is - it's not what you think it is, it rarely is inside a callback, like in this case - perhaps (if you can) change `function(data)` to the arrow notation `(data)=>` - `this` will be what you want – Jaromanda X Nov 14 '16 at 08:11
  • @JaromandaX but if I don´t use .this.getDateRange I can´t call the function. Could you tell me how to do it right then? – BayLife Nov 14 '16 at 08:14
  • I showed one way above ... `=>` notation ... another (common) way is by setting `var self=this` before the `Promise.all` then using `self` instead of `this` inside the callback – Jaromanda X Nov 14 '16 at 08:15
  • Yeah sorry the comment was after you edit. Now it works. Thanks for your help. – BayLife Nov 14 '16 at 08:17
  • or read [this](http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) - pardon the pun – Jaromanda X Nov 14 '16 at 08:17
  • You want to make an answer out of it, so I can accept it? – BayLife Nov 14 '16 at 08:17
  • If you read the link I just posted, you'll see why I wont post an answer :p `this` has been asked about many times on SO :p – Jaromanda X Nov 14 '16 at 08:17
  • haha ok :) thanks for your help buddy! – BayLife Nov 14 '16 at 08:18

0 Answers0