2016-11-11 5 views
0

Ich verwende node/epxress, mysql und bluebird.Async-Versprechen innerhalb async Versprechen mit .join()

Ich mache derzeit eine asynchrone Datenbankoperation, nachdem der Client es angefordert hat. Innerhalb des Callbacks der ersten Datenbankoperation muss ich zuerst einige Berechnungen durchführen und danach zwei weitere Datenbankabfragen durchführen, die benötigt werden, um dem Client das korrekte Ergebnis zu liefern.

Mein Code ist in eine Controller-Klasse unterteilt, die die Get/Post-Anfrage behandelt. In der Mitte eine Serviceklasse für Geschäftslogik, die mit einer Datenbankklasse kommuniziert, die in der Datenbank abfragt.

Ich bin derzeit in der Lage, die erste und zweite Datenbankanforderung durchzuführen.

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

Aber wenn ich versuche, die dritte durchzuführen, stoße ich in Schwierigkeiten. Für eine Lösung dieses Problems lese ich die Bluebird Doc's, die mich auf .all() oder (noch besser) .join() wies. Aber zu versuchen, beide zu benutzen, hat nicht für mich funktioniert.

Wenn ich es mit .join() versuche ist immer Ergebnisse in join is not a function, die ich verwirrend finde, weil ich alle anderen Funktionen verwenden kann. Ich habe auch versucht,

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

zu verlangen, aber nicht einmal das half.

Derzeit benötige ich nur Bluebird als Promise in meiner Datenbankklasse.

Also hier jetzt meine gesamte Serviceklasse.

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

Kann jemand mir ein Beispiel geben, wie man es richtig macht?

EDIT:

Hier ist ein Beispiel-Code Ich bin in meinem databaseCall verwenden, das DB Ergebnis und das Versprechen zurückzukehren

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

Also, weil Sie verwenden '.join() ', verwenden Sie die' Promise', die aus der 'getVacation'-Funktion kommt - so könnte es vorteilhaft sein zu sehen, was es zurückgibt (es ist ein Bluebird-Versprechen). Zweitens geben die [docs] (http://bluebirdjs.com/docs/api/promise.join.html) an, dass Promises an 'join' übergeben werden sollten, also sollte Ihre Zeile vielleicht' .then ((result) => Promise.join (Promise.resolve (Ergebnis), departmentDatabase.countUser (departmentID), departmentDatabase.blockedDaysOfResponsible (departmentID), (a, b, c) => [a, b, c])) ' –

+0

Oder noch besser, mit 'Promise.all':' .then (Ergebnis => Promise.all ([result, departmentDatabase.countUser (departmentID), departmentDatabase.blockedDaysOfResponsible (departmentID)]])) ' –

+0

Ich habe Probleme mit der Syntax in Ihr Promise.all-Beispiel. Könnten Sie das bitte als Antwort formulieren, am besten mit einem Beispiel console.log (a) ;? das würde mir sehr helfen. Das .join() Beispiel läuft immer noch in den 'no a function' Fehler – BayLife

Antwort

0

Promise.join ist schön, aber es könnte Ihre Situation nicht die am besten passen . Promise.all werden mehrere Versprechen kombinieren, wie Sie es in eine einzige Auflösung haben:

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

Dann könnte man dieses Ergebnis (ein Array) verteilt in einem Funktionsaufruf:

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

Promise.all nimmt eine Reihe von Versprechen, wartet darauf, dass alle sie auflösen (oder ablehnen) und fährt dann mit den Ergebnissen in einem geordneten Array in der nachfolgenden .then (oder anderen Versprechen) -Klausel fort.

0

Wenn Sie nach einem Modul suchen, das die Steuerung mit Versprechen leichter macht, möchten Sie vielleicht relign. Promise.all kann hier den Trick, aber wenn Sie die aufgelösten Ergebnisse benötigen, dann relign.parallel oder relign.series könnte besser für Sie sein.

Verwandte Themen