0

I'm trying to create an object of objects in JS but I think I have some problems with the asynchronous execution.

Here is my code:

// Extract data (episode number, characters firstname's) from .docx to JSON

var mammoth = require("mammoth")

function docx2Object (filepath) {
    
    return mammoth.extractRawText({path: filepath})
    .then(function (res) {
        return res.value;
    })
    .then(function (res) {
        let arr = {}
        arr["number"] = "" + res.match(/(?!Episode #)\d+/)
        arr["names"] = [...new Set(res.match(/^[^:\r\n]+(?=:)/gm))]
        return arr
    })
}

function files2JSON (arrayScripts) {
    
    let arr = {}
    let i = 0
    arrayScripts.forEach(function(element) {
        docx2Object(element).then(function (res) {
            arr[i++] = res
            console.log(JSON.stringify(arr, null, '\t'))
        })
    })
    return JSON.stringify(arr, null, '\t')
}

let arrayScripts = ["doc1.docx", "doc2.docx"]
console.log(files2JSON(arrayScripts))

And here is the output:

{}

{
    "0": {
        "number": "10600",
        "names": [
            "Hilary",
            "Jean-Claude",
            "Devon",
            "Jean Claude",
            "Cane",
            "Lily",
            "Jack",
            "Phyllis",
            "Victor",
            "Nikki",
            "Neil",
            "Paul",
            "Dr. Barrett",
            "Christine",
            "Kelly"
        ]
    }
}
{
    "0": {
        "number": "10600",
        "names": [
            "Hilary",
            "Jean-Claude",
            "Devon",
            "Jean Claude",
            "Cane",
            "Lily",
            "Jack",
            "Phyllis",
            "Victor",
            "Nikki",
            "Neil",
            "Paul",
            "Dr. Barrett",
            "Christine",
            "Kelly"
        ]
    },
    "1": {
        "number": "10601",
        "names": [
            "Hilary",
            "Devon",
            "Jean+Claude",
            "Jean + Claude",
            "Jean/Claude",
            "Jean / Claude",
            "Cane",
            "Lily",
            "Jack",
            "Phyllis",
            "Victor",
            "Nikki",
            "Neil",
            "Paul",
            "Dr. Barrett",
            "Christine",
            "Kelly"
        ]
    }
}

My array is empty and my indexes do not match.Can anyone help?

1
  • Did you try to debug it, put bunch of console logs in your then functions. And see which ones execute, which don't and what is happening with your objects. And tell me if I am wrong, but you cant have more than one return, since first one will cancel everything bellow Commented Aug 30, 2017 at 15:57

2 Answers 2

0

I think your problem is with

arrayScripts.forEach(function(element) {
    docx2Object(element).then(function (res) {
        arr[i++] = res
        console.log(JSON.stringify(arr, null, '\t'))
    })
})

The docx2Object call is asynchronous meaning iteration of the forEach will return and execute immediately. This means files2JSON might execute before all of the processing is done.

Most likely what you want to do is store each promise into an array and then use Promise.all() to resolve them all at once and return the promise from Promise.all() and wait on it. Overall the structure of this would look something like

function asyncTask1(task) {
  return getPromise(task);
}

function asyncTask2() {
  var tasks = ["eat", "sleep"];
  var promises = tasks.map(function(task) {
    return asyncTask1(task);
  });
  return Promise.all(promises);
}

asyncTask2().then(function(response) {
  console.log("I ate and slept.");
});

Number one thing that I personally do when debugging async code is just throw a whole bunch of console.logs and see what gets executed when. It really helps seeing the order of execution.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

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

Comments

0

This will help to get your output.As you are using global wrong increment count and also mammoth.extractRawText() method containing wrong code.

// Extract data (episode number, characters firstname's) from .docx to JSON
var mammoth = require("mammoth");

function docx2Object (filepath) {

  return mammoth.extractRawText({path: filepath})
      .then(function (res) {
        return res.value;
      }).then(function (res) {
        var arr = {};
        arr["number"] = "" + res.match(/(?!Episode #)\d+/);
        //arr["names"] = [...new Set(res.match(/^[^:\r\n]+(?=:)/gm))];
        return arr
      });

}

function files2JSON (arrayScripts) {
  var arr = {};

  arrayScripts.forEach(function(element,index) {
    docx2Object(element).then(function (res) {
      arr[index++] = res;
      console.log(res,index)
      console.log(JSON.stringify(arr, null, '\t'));
    })
  });
  return JSON.stringify(arr, null, '\t');
}

var arrayScripts = ["doc1.docx", "doc2.docx"];
console.log(files2JSON(arrayScripts));

Comments