const tj = require('@mapbox/togeojson');
const fs = require('fs');
const gpxToJson = async function (trailSlug) {
// node doesn't have xml parsing or a dom. use xmldom
DOMParser = require('xmldom').DOMParser;
fs.readdir(`./public/traildata/${trailSlug}/gpxFiles/`, (err, files) => {
let newGpx;
files.forEach(async (item, i) => {
const promise = new Promise((res, rej) => {
fs.readFile(
`./public/traildata/${trailSlug}/gpxFiles/${item}`,
'utf8',
async function (err, data) {
const gpx = await new DOMParser().parseFromString(data);
const converted = await tj.gpx(gpx);
console.log(typeof converted);
converted.features[0].properties.name = item
.replace('-', ' ')
.split('.')[0];
if (i === 0) {
newGpx = converted;
}
if (i > 0) {
newGpx.features.push(converted.features[0]);
}
if (i === files.length - 1) {
// console.log(newGpx);
fs.writeFile(
`./public/traildata/${trailSlug}/mastergeoJSON`,
JSON.stringify(newGpx),
'utf-8',
(err) => {
if (err) throw err;
console.log('The file has been saved');
}
);
}
res(converted);
}
);
});
await promise;
});
});
};
gpxToJson('terra-cotta');
Hey there, I am trying to make a program that converts GPX files into one GeoJSON File. Everything seems to be going well so far except for every one in 5 times I run the code, I get a TypeError: Cannot read properties of undefined error from "newGpx.features.push(converted.features[0])"
I know the file is an object (as i have done the console.log(typeof converted) and it comes back as an object), I tried promisifying the entire forEach loop (but may have had an issue with the implementation).
Does anyone have a resource that might steer me in the right direction?
Thanks in advance.
Here's a much simpler version that uses a for
loop which is promise-aware (a .forEach()
loop is not promise-aware) and uses the built-in promise versions of readdir()
, readFile()
and writeFile()
which, when combined with await
makes the code a lot simpler.
const tj = require('@mapbox/togeojson');
const fsp = require('fs').promises;
const DOMParser = require('xmldom').DOMParser;
const gpxToJson = async function (trailSlug) {
const srcDir = `./public/traildata/${trailSlug}/gpxFiles/`;
const files = await fsp.readdir(srcDir);
let newGpx;
for (let file of files) {
const fullPath = path.join(srcDir, file);
const fileData = await fsp.readFile(fullPath, {encoding: 'utf8'});
const gpx = new DOMParser().parseFromString(fileData);
const converted = await tj.gpx(gpx);
converted.features[0].properties.name = file.replace('-', ' ').split('.')[0];
if (!newGpx) {
newGpx = converted;
} else {
newGpx.features.push(converted.features[0]);
}
}
await fsp.writeFile(`./public/traildata/${trailSlug}/mastergeoJSON`, JSON.stringify(newGPx), { encoding: 'utf8' });
};
gpxToJson('terra-cotta').catch(err => {
console.log(err);
});