2016-11-11 141 views
0

我正在使用node/epxress,mysql和bluebird。使用.join在异步承诺中调用异步承诺

我现在正在做一个异步数据库操作后,客户端请求它。在第一个数据库操作的回调中,我必须首先执行一些计算,然后再执行两个数据库查询,这些查询是为客户端提供正确结果所必需的。

我的代码被分成一个Controller类,它处理get/post请求。在中间是业务逻辑的服务类,它与在数据库中查询的数据库类进行对话。

我目前能够执行第一个和第二个数据库请求。

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

但是,当试图执行第三次我遇到麻烦。 对于这个问题的解决方案,我阅读了Bluebird Docs,它指向我.all()或(更好).join()。但试图使用他们中的任何一个都没有为我工作。

如果我尝试.join()总是导致join is not a function,这让我感到困惑,因为我可以使用所有其他功能。我也试过要求

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

但是这甚至都没有帮助。

目前我只需要Bluebird作为我的数据库类中的Promise。

所以这里现在我的整个服务类。

'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(); 

是否有人能够给我一个例子如何做到这一点的权利?

编辑:

这里用我的databaseCall内,返回DB结果和承诺

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

所以,因为你使用'。join()',你使用'getVacation'函数出来的'Promise' - 所以看看它返回的是什么(确保它是一个Bluebird Promise)可能是有利的。其次,[docs](http://bluebirdjs.com/docs/api/promise.join.html)指定Promises应该传递给'join',所以也许你的行应该读取'.then((result)=> Promise.join(Promise.resolve(result),departmentDatabase.countUser(departmentID),departmentDatabase.blockedDaysOfResponsible(departmentID),(a,b,c)=> [a,b,c]))' –

+0

或者更好, 'Promise.all':'.then(result => Promise.all([result,departmentDatabase.countUser(departmentID),departmentDatabase.blockedDaysOfResponsible(departmentID)])]))' –

+0

我有一些麻烦的语法你的Promise.all例子。您能否将此作为答案来制定,最好以console.log(a)为例;?这会帮助我很多。 .join()示例仍然会出现在“不是函数”错误中 – BayLife

回答

0

Promise.join是很好的示例代码I'm,但它可能不适合您的情况最好。 Promise.all将结合几个诺言就像你有没有为一个决议:

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

然后,你可以传播这个结果(数组)到一个函数调用:

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

Promise.all需要数组承诺,等待所有人解决(或拒绝),然后将结果以有序数组的形式继续输入后续的.then(或其他承诺)条款。

0

如果您正在寻找一个模块,使承诺的控制流程更容易,那么您可能会喜欢relignPromise.all可能会在这里做的伎俩,但如果你需要解决的结果,那么relign.parallelrelign.series可能会对你更好。