Hi everyone, I have created a functionality which allows users to upload an Excel file containing addresses and I'm then geocoding those addresses to get statistics within the buffer. My issue is that the order of my addresses changes when geocoding.
document.getElementById("done-button").onclick = () => {
var fileInput = document.getElementById('fileInput');
var file = fileInput.files[0];
if (file) {
var reader = new FileReader();
reader.onload = function (e) {
var data = e.target.result;
var workbook = XLSX.read(data, { type: 'binary' });
var sheetName = workbook.SheetNames[0];
var sheet = workbook.Sheets[sheetName];
var dataArray = XLSX.utils.sheet_to_json(sheet, { header: 1 });
list_address = dataArray.flat()
uniqueAddressID2 = list_address
const params=[]
const geocode = "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer";
for (var i = 0; i < list_address.length; i++) {
//const addressinput = list_address[i]
params[i] = {
address: {
address: list_address[i],
},
countryCode: "CAN",
outSpatialReference: SpatialReference.WGS84
};
}
for (var i = 0; i < params.length; i++) {
locator.addressToLocations(geocode, params[i]).then((results) => {
if (results.length) {
const result = results[0];
const point = new Point({
x: result.location.x,
y: result.location.y,
spatialReference: { wkid: 4326 }
});
address_geo.push(point)
BatchBufferGeom(address_geo)
};
});
};
}
reader.readAsBinaryString(file);
} else {
alert('Please select a file.');
}
}
Is the order based on a sorting definition for a particular field or set of fields? If not, you would have to reference the original order and copy each geocode row out individually in the order you want.
@BlakeTerhune so in the second for loop (see below). The list of addresses (params) is still in order but the results change it
for (var i = 0; i < params.length; i++) {
}
Are you sure they're in the right order when read into list_address and params?
yup, I ran console.log on both and the order was correct
I think I know what's happening. When you send the locations to the geocoder, it returns a promise which is resolved whenever it is completed, which may or may not be in the order it was sent. So, the result list is jumbled. As for how to fix it... I don't know.
If you adjust the logic of how you are doing things a bit, you can create an array of promises and wait for them all to complete. It does require another loop to do your buffer, but this could help you maintain the order you are looking for.
const geocodePromises = params.map(
(param) => locator.addressToLocations(...)
);
Promise.all(geocodePromises).then((results) => {
// do something with results
});
Note, you can use Promise.all or Promise.allSettled. The result signatures are different, but depends on your needs.
Hi @ReneRubalcava I used the following code, however, I'm getting an error at location.x
const geocodePromises = params.map(
(param) => locator.addressToLocations(geocode, param)
)
Promise.all(geocodePromises).then((results) => {
for(var i=0; i<results.length; i++) {
const result= results[i]
const point = new Point({
x: result.location.x,
y: result.location.y,
spatialReference: { wkid: 4326 }
});
console.log(result)
address_geo.push(point)
BatchBufferGeom(address_geo)
}
This probably means there was not a result for that address, so you probably need to add some checks that you have a valid result.
Ah, yes, good point! You would probably have to leverage the await operator.