2

New to concept of callbacks and promises. I'm trying to read contents of a directory which is correctly returning the addresses but this code is only printing console.log(value) and the console.log in the function getAccount "gettin info..." but nowhere printing the balance the api is getting closed and the process completes, I dont understand this because the address is being passed and the first console.log is printing inside the function but not doing further job. when i remove the fs.readdir and files.foreach and pass a single value to getAccount its working perfectly fine. No errors or bugs , its a runtime error and im guessing related to callbacks

'use strict';
const RippleAPI = require('ripple-lib').RippleAPI;
const testFolder = '/home/ripple/.keystore';
const fs = require('fs');
const api = new RippleAPI({server: 'wss://s1.ripple.com'});

function getAccount(address) {
        var balance = 0.0;
        console.log("getting info  for :"+address);
        return api.getAccountInfo(address).then(info => {
        var balance = info.xrpBalance;
        console.log("balance of "+address+" is "+balance);
        return balance;
        });
}

api.connect().then(() =>  {
        fs.readdir(testFolder, function(err, files) {
//      console.log("Total no of wallets : "+files.length);
//      for (var i =3000, len=3200; i < len; i++) {
//              var ad = files[i];
//              console.log(ad + "\t" + typeof(ad));
//              if(!xwallets.includes(ad))
                files.forEach(function(value) {
                        getAccount(value).then(balance => {console.log(balance); });
                        console.log(value);
                });
//              console.log("running for index : "+i+" filedata :"+files[i]);
//      }
        });
//      console.log(balance);
}).then(() => {
        return api.disconnect();
}).then(() => {
        console.log("done and disconnected");
}).catch(console.error);
3
  • 1
    Code needs to be pasted into your question as text, not as an image. Commented Jan 20, 2018 at 6:50
  • @jfriend00 im sorry i using putty on ubuntu which doesnt support copy/paste , i have been lazy for tht Commented Jan 20, 2018 at 7:06
  • PuTTY on Linux uses the PRIMARY X Window selection: askubuntu.com/a/654610/780349 Commented Jan 20, 2018 at 7:53

1 Answer 1

1

You really don't want to mix asynchronous operations that return a promise with those that take a direct callback. It's hard to write good robust code when mixing like that. So, since you are already using with promises in a number of operations, it's best to take the remaining async operations and "promisify" them so you can use them with promises. Then, you can take advantage of all the clean error propagation and chaining of promises.

Then, secondly, you have to make sure all your asynchronous operations in a loop are properly chained to the parent promise. To do that here, we will accumulate the promises from getAccount() in the loop into an array of promises. Then, after the loop, we can tell when they're all done using Promise.all() and then return that promise from readdir() so that they will all be properly chained to the parent promise.

This will then make sure everything inside the loop finishes before the parent resolves and before you call api.disconnect().

Here's what that would look like:

'use strict';
const RippleAPI = require('ripple-lib').RippleAPI;
const testFolder = '/home/ripple/.keystore';
const fs = require('fs');
const api = new RippleAPI({server: 'wss://s1.ripple.com'});

function getAccount(address) {
    var balance = 0.0;
    console.log("getting info  for :"+address);
    return api.getAccountInfo(address).then(info => {
        var balance = info.xrpBalance;
        console.log("balance of "+address+" is "+balance);
        return balance;
    });
}

// promisify readdir
const readdir = util.promisify(fs.readdir);

api.connect().then(() =>  {
    return readdir(testFolder).then(function(files) {
        const promises = [];
        files.forEach(function(file) {
            console.log(file);
            promises.push(getAccount(file).then(balance => {
                console.log(balance); 
                // make balance be the resolved value for this promise
                return balance;
            }));
        });
        // make sure we are waiting for all these promises to be done
        // by chaining them into the parent promise
        return Promise.all(promises);
    });
}).then(balances => {
    // process balances array here
    console.log(balances);
    return api.disconnect();
}, err => {
    // disconnect, even in the error case, but preserve the error
    console.error(err);
    return api.disconnect().then(() => {throw err;})
}).then(() => {
    console.log("done and disconnected");
});

Summary of changes made:

  1. Promisify fs.readdir() so we can use promise with it
  2. Change how we call readdir() to use promises
  3. Collect getAccount() promises inside of .forEach() into an array of promises
  4. Add return Promise.all(promises) so that we wait for all those promises to be done and so that it is chained into the parent promise
  5. Make balance be the resolved value of each promise in the .forEach() loop, even after logging its value
  6. Make sure we're calling api.disconnect() even in the error cases
  7. After logging error, preserve the error value as the reject reason
Sign up to request clarification or add additional context in comments.

Comments

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.