2

I have confusing code that I'd like to modularize. I have a general ledger implemented in Mongodb. Transferring credits from john to adam appends the following document in the db.dummyTx:

{
  "debitAccount": "john",
  "creditAccount": "adam",
  "amount": 10
}

I'd like to create a single function transfer(from, to, amount, callback()) where callback receives the transaction document/object.

I've created the following using the async module:

function transfer(from, to, amount, acallback) {
  async.waterfall([
      function(callback) {
        userBalance(from);
        userBalance(to);
        callback(null);
      },
      function(callback) {
        var transaction = new dummyTx();
        transaction.creditAccount = from; // in the account of the sender
        transaction.debitAccount = to; // with reference to the reciever
        transaction.amount = amount; // of the given amount
        transaction.save(function(err) {
          callback(null, transaction);
        });
      },
      function(transaction, callback) {
        console.log("Credited User " + transaction.creditAccount +
          " and debited User " + transaction.debitAccount + " by amount " +
          transaction.amount + "credits");
        callback(null, transaction);
      },
      function(transaction, callback) {
        userBalance(transaction.creditAccount);
        userBalance(transaction.debitAccount);
        callback(null, transaction);
      }
    ],
    acallback(err, transaction)
  );
}

My rationale was that if I pass function(err,transaction){if err console.log(err);} as acallback, it would run as the final callback in the end. However, it says err is undefined in acallback(err, transaction)

Bear with me, I just discovered async yesterday, so I'm a figurative five year old.

My second thought was to save the chain of functions into an Array named transfer and to call it as async(transfer,function(err,transaction){if err console.log(err)}; if I can't get this to work.

Edit: I'd also like the acallback parameter to be optional.

2
  • Why do you ignore errors from transaction.save? Also, why do you use waterfall at all here when you have only a single async function? Commented May 11, 2015 at 20:41
  • @Bergi It's simple really, because I'm stupid. Thank you, I've now changed it to callback(err, transaction). And I just realized that I could do the same thing with async.series. I've got another problem now though, the acallback parameter now executes after the third function, with a null error value, and then outputs the final function normally when I run transfer(2, 1, 2, function(err, transaction) { if (err) { console.log(transaction); }});. Pastebin of output Commented May 11, 2015 at 21:00

1 Answer 1

1

If you have defined the function acallback, then you should just pass that, and not the parameters. In other words, instead of this:

...
      }
    ],
    acallback(err, transaction)
  );
}

...use this:

...
      }
    ],
    acallback
  );
}

To make acallback() optional, you can do a number of things. A couple things that leap to mind:

  • Before calling, async.waterfall(), check to see if acallback() is defined. If it is not, set it to a no-op function.

  • Before calling async.waterfall(), check to see if acallback() is defined. If it is not, invoke async.waterfall() without it. If it is, invoke it with it.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for that, the code runs now. Only, the acallback is executed after the third function, instead of the last. I ran it with transfer(2,1,2,function(err, transaction){console.log(transaction);});. Pastebin to output. Also, the to in the third function is now undefined.
If a function in the waterfall sends an error, the waterfall is aborted and the callback invoked immediately. So check the value of err in your callback and it will hopefully indicate what's going wrong.
It's null, however, I notice that the value of to in the third function is now undefined.
It's undefined because of a typo in the code, sorry. I fixed it. However, acallback is still being executed after the third function, with the err outputing to null

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.