【问题标题】:Calling async promises inside async promise using .join()使用 .join() 在异步承诺中调用异步承诺
【发布时间】:2016-11-11 08:58:35
【问题描述】:

我正在使用 node/epxress、mysql 和 bluebird。

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

我的代码被分成一个控制器类,它处理 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 Doc´s,它指向我 .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 中使用的示例代码,用于返回数据库结果和承诺

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

【问题讨论】:

  • 所以因为您使用的是.join(),所以您使用的是来自getVacation 函数的Promise - 因此查看它返回的内容可能是有利的(确保它是蓝鸟承诺)。其次,docs 指定应将 Promises 传递给join,因此您的行可能应为.then( (result) =&gt; Promise.join( Promise.resolve(result), departmentDatabase.countUser(departmentID), departmentDatabase.blockedDaysOfResponsible(departmentID), (a, b, c) =&gt; [a, b, c] ) )
  • 或者更好,Promise.all: .then(result =&gt; Promise.all([result, departmentDatabase.countUser(departmentID), departmentDatabase.blockedDaysOfResponsible(departmentID)])]))
  • 我在您的 Promise.all 示例中遇到了一些语法问题。您能否将其表述为答案,最好使用示例 console.log(a);?这对我有很大帮助。 .join() 示例仍然遇到not a function 错误
  • 啊,明白了。你想为此创建一个答案,否则我会的。 .then(result =&gt; Promise.all([result, departmentDatabase.countUser(departmentID), departmentDatabase.blockedDaysOfResponsible(departmentID)])).spread(function(a, b, c){ console.log(a); console.log(b); console.log(c); return 1; })

标签: javascript node.js express asynchronous bluebird


【解决方案1】:

Promise.join 很好,但它可能不适合您的情况。 Promise.all 将像您一样将几个承诺组合成一个解决方案:

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

然后您可以将该结果(一个数组)传播到一个函数调用中:

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

Promise.all 接受一个 Promise 数组,等待它们全部解决(或拒绝),然后将结果以有序数组的形式继续输入到随后的 .then(或其他 Promise)子句中。

【讨论】:

    【解决方案2】:

    如果您正在寻找一个可以更轻松地使用 Promise 进行控制流的模块,那么您可能会喜欢relignPromise.all 可以在这里解决问题,但如果您需要解析结果,那么 relign.parallelrelign.series 可能更适合您。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-10
      • 1970-01-01
      • 2018-07-01
      • 2017-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多