0

Here is my entire code, and what I want to avoid are all the moveAllBank, moveAllReceipt moveAllExpense functions if possible. The code below works fine, I just wish there was a smarter way of doing it. Its really hard to understand how the different promises passes data between each other.

// 
// Find all bank accounts
// 
var bankModel = require('../models/bankModel');
var bankTable = mongoose.model('bankModel');
var bankArray = [];
var findAllBank = new Promise(
    (resolve, reject) => {
    bankTable.find({}
    ,function(err, data) {
        if (!err) {
            resolve(data);
        } else {
            reject(new Error('findBank ERROR : ' + err));
        }
    });
});
let moveAllBank = function (data) {
    bankArray = data;
    console.log("receiptArray Result: " + JSON.stringify(data, null, 4));
};


// 
// Find the RECEIPT for each bank account
// 
var receiptModel = require('../models/receiptModel');
var receiptTable = mongoose.model('receiptModel');
var receiptArray = [];
let findAllReceipts = function (accountArray) {
    return Promise.all(bankArray.map(findReceipts));
};
function findReceipts(account) {
    return new Promise((resolve, reject) => {
        receiptTable.find({account: account._id}, function (err, data) {
            if (!err) {
                console.log("findReceipts Result: " + JSON.stringify(data, null, 4));
                resolve(data);
            } else {
                reject(new Error('findReceipts ERROR : ' + err));
            }
        });
    });
}
let moveAllReceipt = function (data) {
    receiptArray = data;
    console.log("receiptArray Result: " + JSON.stringify(data, null, 4));
};


// 
// Find the EXPENSE for each bank account
// 
var expenseModel = require('../models/expenseModel');
var expenseTable = mongoose.model('expenseModel');
var expenseArray = [];
let findAllExpense = function (accountArray) {
    console.log("=====EXPENSE====")
    console.log("accountArray Result: " + JSON.stringify(accountArray, null, 4));
    return Promise.all(bankArray.map(findExpense));
};
function findExpense(account) {
    return new Promise((resolve, reject) => {
        expenseTable.find({account: account._id}, function (err, data) {
            if (!err) {
                console.log("findExpense Result: " + JSON.stringify(data, null, 4));
                resolve(data);
            } else {
                reject(new Error('findExpense ERROR : ' + err));
            }
        });
    });
}
let moveAllExpense = function (data) {
    expenseArray = data;
    console.log("expenseArray Result: " + JSON.stringify(data, null, 4));
};


// 
// Send the result
// 
let sendResult = function (data) {
    res.json({error:false,  "bank":bankArray, "receipt":receiptArray, "expense":expenseArray})
};  


// 
// Run the promises
// 
findAllBank
    .then(moveAllBank)
    .then(findAllReceipt)
    .then(moveAllReceipt)
    .then(findAllExpense)
    .then(moveAllExpense)
    .then(sendResult)
    .catch(err => {
        console.error(err);
        console.log("getbankAccountReport ERR: " + err);
        res.json({error:true,err})
    });
torbenrudgaard
  • 2,375
  • 7
  • 32
  • 53
  • 1
    Do you mean `.then(() => res.json`? –  May 18 '17 at 13:36
  • `.then(() =>bankArray)` is that what you mean torazaburo? – torbenrudgaard May 18 '17 at 13:39
  • Every then method has the same signature, you need to pass it functions. – Axnyff May 18 '17 at 13:40
  • your `then` code should indeed be a function - just use the `data => bankData = data` approach to register an anonymous function inline – Ovidiu Dolha May 18 '17 at 13:42
  • @OvidiuDolha I tried it but get no result. Even thou the function runs perfectly and actually produce data, there is nothing put into the array with `.then(expenseArray => findAllExpense(bankArray))` – torbenrudgaard May 19 '17 at 04:19
  • @torbenrudgaard That would suggest that they *don't* run perfectly fine. Please find a way, and show us, how to actually call the functions (including `findBank()`?) with their expected parameters, then we still can figure out how to collect your results. – Bergi May 19 '17 at 04:32
  • When you have *working* code, and you are asking for a review to improve certain aspects, codereview.stackexchange.com might be a better place. – GhostCat May 19 '17 at 12:49

1 Answers1

0

You want

findBank
  .then(bank => findAllReceipts(bank)
    .then(receipt => bank.findAllExpense(bank)
      .then(expense =>
        res.json({error:false, bank, receipt, expense})
      )
    )
  )
  .catch(err => res.json({error:true,err});

Or just

try {
  const bank = await findBank;
  const receipt = await findAllReceipts(bank);
  const expense = await findAllExpense(bank);
  res.json({error: false, bank, receipt, expense});
} catch(error) {
  res.json({error});
}

To use await, of course the function must be marked as async.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • None of them work - In your first example only the findBank() produce a result, none of the other .then's work. And in the second example all await give errors at the await function(); `SyntaxError: Unexpected identifier` – torbenrudgaard May 19 '17 at 04:12
  • @torbenrudgaard You need to make your function `async` for that, and possibly enable the feature in your transpiler. However, the snippets are equivalent, so if one won't work then the other will neither. – Bergi May 19 '17 at 04:33
  • @Bergi I like the promise structure better in this case. But how do you get the result from a promise and how do you send results to the promise? That is my biggest issue here. I know promises send the result to each other by default, but can you change that and send other things? – torbenrudgaard May 19 '17 at 06:51
  • @torbenrudgaard promises send their results to their *callbacks*. Please don't confuse promises for the functions that create them. And what you do with the parameters in your callback functions is entirely your choice. – Bergi May 19 '17 at 06:57
  • @Bergi I read the other post (the one that replaces mine as duplicate) and you give some great examples and information. You are like the godfather of promises :-)) But im still pretty new to async programming so I still cant understand how I can implement your suggestions. I updated my question and put all the code and rephrased my question. – torbenrudgaard May 19 '17 at 07:14
  • @torbenrudgaard The code in torazaburos answer is exactly what I am suggesting (and the many other ways from the duplicate :D). The only reason this would not work with your `findAllReceipts` and `findAllExpense` functions is that they ignore their `accountArray` parameter and refer to the global `bankArray` instead. Also I had expected `findBank` to be a function that needed to be called, not a promise - I'll edit this answer – Bergi May 19 '17 at 07:26
  • @Bergi so the only way is (like I do) to make the moveAll functions and make them put data into the arrays? – torbenrudgaard May 19 '17 at 07:28
  • @torbenrudgaard No, you don't need those. Change your `findAll*` functions to consider their parameters, and use the code from this answer. – Bergi May 19 '17 at 14:30