Reputation: 139
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?
Upvotes: 0
Views: 80
Reputation: 93
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));
Upvotes: 0
Reputation: 576
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.log
s 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
Upvotes: 1