Accepted answer

I would suggest you do it with a recursive function.

In the following example you can use loadFilesAndCalculateSum() like the d3.text() but instead of one string it takes an array of strings and the callback gets the calculated sum instead of the text of a file.

 * load all files and calculate the sum of the values
 * @param  {Array}    filenames Array with filenames as string
 * @param  {Function} cb        Callback function, gets the sum as param
 * @param  {number}   sum       The initial sum   
 * @param  {number}   i         Starting index for filenames
 * @return {void}
function loadFilesAndCalculateSum(filenames, cb, sum, i) {
  sum = sum || 0;
  i = i || 0;
  d3.text(filenames[i], function(error, text) {
    //parse the rows and reduce them
    sum += d3.csv.parseRows(text).reduce(function(prev, curr) {
      //return previous sum + this rows sum
      return prev + d3.sum(curr, function(d){return +d;})

    if(i < filenames.length - 1){
      //load next file
      loadFilesAndCalculateSum(filenames, cb, sum, i+1);
    } else {
      //call the callback with the final sum

var filenames = ["file1.txt", "file2.txt", "file3.txt"];

loadFilesAndCalculateSum(filenames, function(sum){
  //do something with the total sum

To clarify this. you have to do the processing of sum inside of the callback function where I put the comment do something with the total sum. This function is still executing async. That means, that everything you write after the loadFilesAndCalculateSum() function will possibly execute before the code inside the callback. You can find a little longer introduction to async javascript here

//this is executed first
loadFilesAndCalculateSum(filenames, function(sum){
  //do something with the total sum
  //this is executed third, when all files are loaded and the sum is calculated

//code after this point is executed second, while the files are being loaded.

If you already have a function that does something with the sum, you can pass this function to the loadFilesAndCalculateSum as second parameter. This is possible because functions are so called first class citizens:

var addthis = 5;

function doSomethingWithTheSum(sum) {
  //everything you want to do with the sum goes inside this function.

  //from here you could call other functions and pass the sum.

  //or you use the sum inside this function
  var newsum = sum + addthis;
      .text(function(d){ return d;});

loadFilesAndCalculateSum(filenames, doSomethingWithTheSum);

You can pass functions just like any other variable. in the first example I called the second parameter of the loadFiles... function cb which is the usual abbreviation for callback. As stated in the doc comment, this param should be of type Function.

In the end of the loadFiles... function I the callback function gets called by

//call the callback with the final sum

Here the sum is given to the callback function as first parameter. Therefore if you pass a function, it should take a single param, like the anonymous function in the first example or the doSomethingWithTheSum function in the example above.

Related Query

More Query from same tag