In this function, I am trying to run 2 different ajax requests (3 options, only 2 will run depending on if statements). addDep()
, and addCust()
functions both have an ajax request in them and get sent an url. However, I need that ajax function to run and complete before the code in the .then function being called after it runs. Right now the code runs but has null values because it hasn't got data1 or data2 back from the ajax function. How do I fix this?
function builder(){
var beforeDate = dateConv(document.getElementById('Before').value);
var afterDate = dateConv(document.getElementById('After').value);
var url = "http://localhost:8181/GRAIN/grain_map?start="
url += afterDate;
url += "&end=";
url += beforeDate;
url += "&attributes=DATE-SHIPPED+DESTINATION-NAME+DESTINATION";
ajaxReq(url).then(function (jsonString) {
for (i=0; i < jsonString.grain_map.length; i++){
destinationArray.push(jsonString.grain_map[i].DESTINATION);
}
for (i = 0; i < destinationArray.length; i++){
if (destinationArray[i] == ""){
continue;
}
if (destinationArray[i].length == 3 || destinationArray[i].length == 2){
var destCode = destinationArray[i];
addDep(destCode).then(function (data1) {
var address = "";
var depArray = data1.dep_address[0].ADDRESS;
for(i = 0; i < depArray.length; i++){
address += data1.dep_address[0].ADDRESS[i] + " ";
}
addressArray.push(address);
}).catch(function (err) {
console.error(err);
});
}else if (destinationArray[i].length == 6){
var destCode = destinationArray[i];
addCust(destCode).then(function (data2) {
var address = "";
var depArray = data2.customer_address[0].ADDRESS;
for(i = 0; i < depArray.length; i++){
address += data2.customer_address[0].ADDRESS[i] + " ";
}
addressArray.push(address);
}).catch(function (err) {
console.error(err);
});
}
}
}).catch(function (err) {
console.error(err);
});
}
As it stands:
builder()
returns undefined
- it should return Promise.undefined
- it should return Promise.undefined
- they could (and should) return String.addDep()
or addCust()
are not aggregated - there's no Promise.all()
.destinationArray
and addressArray
, resulting in some guesswork on my part.Array methods .map(), .filter() and .join() allow the code to be simplified
function builder() {
var beforeDate = dateConv(document.getElementById('Before').value);
var afterDate = dateConv(document.getElementById('After').value);
var url = `http://localhost:8181/GRAIN/grain_map?start=${afterDate}&end=${beforeDate}&attributes=DATE-SHIPPED+DESTINATION-NAME+DESTINATION`;
return ajaxReq(url)
// ^^^^^^
.then(jsonString => {
var promises = jsonString.grain_map
.map(item => {
var destcode = item.DESTINATION || '';
switch(destCode.length) {
case 2:
case 3:
return addDep(destCode)
// ^^^^^^
.then(data => data.dep_address[0].ADDRESS.join(' '))
.catch(error => `addDep: ${destCode}: ${error.message}`); // inject message in place of missing address
break;
case 6:
return addCust(destCode)
// ^^^^^^
.then(data => data.customer_address[0].ADDRESS.join(' '))
.catch(error => `addCust: ${destCode}: ${error.message}`); // inject message in place of missing address
break;
default:
return null;
// ^^^^^^
}
})
.filter(p => !!p); // filter out any nulls leaving just Promises
return Promise.all(promises);
});
}
Back in the caller ...
builder()
.then(addressArray => {
// do something with addressArray.
})
.catch(err => {
console.error(err);
throw error; // unless this promise chain is at the topmost level of an event thread.
});
Notes:
destinationArray
disappears completely - it was (probably) never necessary.Promise.all(promises)
to follow its error path on first error encountered.addressArray
is now delivered by the Promise returned by builder()
.