Calling async promises inside async promise using .join()

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

I´m currently doing an async database operation after the client request it. Inside the callback of the first database operation I have to perform some calculations first and afterwards doing two more database queries which are required to provide the client the correct result.

My Code is separated into a Controller class, which handles the get/ post request. In the middle a service class for business logic, which talks to a database class which queries in the database.

I´m currently able to do perform the first and second database request.

getVacation(departmentID) {

        return departmentDatabase.getVacation(departmentID)
            .then(result => [ result, result.map(entry => this.getDateRange(new Date(entry.dateFrom), new Date(entry.dateTo))) ])
            .spread(function(result, dateRange){
                var mergedDateRange = [].concat.apply([], dateRange);
                var counts = {};
                mergedDateRange.forEach(function(x) { counts[x] = (counts[x] || 0)+1; });

                return [{"vacationRequest": result, "dateRange": dateRange, "countedDateRange": counts}];
            })
             .then( result => [result, departmentDatabase.countUser(departmentID)])
             .spread(function (result, userOfDepartmentCount){
                console.log(userOfDepartmentCount);
                console.log(result);
                //console.log(blocked);

                return departmentID; //return just for not running into timeout
            })
            .catch(err => {
                // ...do something with it...
                // If you want to propagate it:
                return Promise.reject(err);
                // Or you can do:
                // throw err;
            });
    }

But when trying to perform the third I´m running into trouble. For a solution of this problem I read the Bluebird Doc´s, which pointed me to .all() or (even better) .join() . But trying to use either of them didn´t worked for me.

If I try it with .join() is always results in join is not a function , which I find confusing because I can use all other function. I also tried to require

var Promise = require("bluebird");
var join = Promise.join;

But not even this helped.

Currently I just require Bluebird as Promise in my database class.

So here now my entire service class.

'use strict';

var departmentDatabase = require('../database/department');
var moment = require('moment');

class DepartmentService {
    constructor() {
    }

    getVacation(departmentID) {

        return departmentDatabase.getVacation(departmentID)
            .then(result => [ result, result.map(entry => this.getDateRange(new Date(entry.dateFrom), new Date(entry.dateTo))) ])
            .spread(function(result, dateRange){
                var mergedDateRange = [].concat.apply([], dateRange);
                var counts = {};
                mergedDateRange.forEach(function(x) { counts[x] = (counts[x] || 0)+1; });

                return [{"vacationRequest": result, "dateRange": dateRange, "countedDateRange": counts}];
            })
            //THIS DOES NOT WORK
            .join(result => [result, departmentDatabase.countUser(departmentID), departmentDatabase.blockedDaysOfResponsible(departmentID)])
            .spread(function (result, userOfDepartmentCount, blocked){
                console.log(userOfDepartmentCount);
                console.log(result);
                console.log(blocked);

                return departmentID;
            })
            .catch(err => {
                // ...do something with it...
                // If you want to propagate it:
                return Promise.reject(err);
                // Or you can do:
                // throw err;
            });
    }

    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;
    }
}

module.exports = new DepartmentService();

Is someone able to give me an example how to do it right?

EDIT:

Here an example code I´m using inside my databaseCall, to return the db result and the promise

return Promise.using(dbConnection.getConnection(), function (conn) {
            return conn.queryAsync(sql, [departmentID])
                .then(function (result) {
                    return result;
                })
                .catch(function (err) {
                    return err;
                });
        });

Promise.join is nice, but it might not suit your situation the best. Promise.all will combine several promises like you have there into a single resolution:

.then(result => Promise.all([result, departmentDatabase.countUser(departmentID), departmentDatabase.blockedDaysOfResponsible(departmentID)])]‌​))

Then you could spread that result (an array) into a function call:

.spread(function(a, b, c) {
    console.log("Results", a, b, c);
});

Promise.all takes an array of Promises, waits for all of them to resolve (or reject), and then continues with the results in an ordered array into the subsequent .then (or other promise) clause.


If your looking for a module that makes control flow with promises easier then you might like relign. Promise.all may do the trick here, but if you need the resolved results, then relign.parallel or relign.series might be better for you.

链接地址: http://www.djcxy.com/p/55492.html

上一篇: 在JavaScript中的异步函数中捕获所有承诺拒绝

下一篇: 使用.join()调用异步承诺内的异步承诺