2016-11-11 144 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可能會對你更好。