Reputation: 629
I wrote a function to filter a time interval from an array.
The function seems to work and prints skip and accept were appropriate and prints no error.
However, it results in an empty array.
getDate()
is a function which returns a date so it can be resolved to a time using getTime()
. That works.
async function getInterval(climatedata,harvestdate,period) {
return new Promise(function(resolve, reject) {
getDate(harvestdate,-1*period).then((sval)=>{
let start = sval.getTime();
getDate(harvestdate,0).then(async(eval)=>{
let end = eval.getTime();
let filtered = await Promise.all(climatedata.filter((curVal,index,arr) => {
getDate(curVal[0]).then((tval)=>{
let td = tval.getTime();
//console.log(start,td,end);
if(td >= start && td <= end) {
console.log("accept"); //although this is printed for the expected subset, nothing is in the filtered array.
return true;
} else {
//console.log("skip");
return false;
}
}).catch((err)=>{console.log(err);});
}));
console.log("filtered",filtered); //here I would expect an array with some rows.
//console.log("bef",climatedata.length,"aft",filtered.length); //this is always bef 8000 aft 0
resolve(filtered);
});
});
});
}
I also tried a sligth variant using .then() on Promise.all
but to no avail.
What am I doing wrong? Thank you, Jens
Upvotes: 0
Views: 1209
Reputation: 31983
So, there's a few issues with your code.
First, your actual question. Note that filter
returns a new array with elements that pass the test function. To pass the test function, any truthy value returned in that iteration of the function will mean that the item at that index in the array should pass. So, you have:
await Promise.all(climatedata.filter((curVal,index,arr) => {
getDate(curVal[0])...
};
Your first immediate problem is that you aren't returning anything in the filter's callback function, which means you are returning undefined
in each iteration of the filter. undefined == false
, so the test does not pass for that iteration. Since none of the tests pass, what you really end up with is:
await Promise.all([undefined, undefined, ...])
Which will indeed resolve to an array of undefined
.
Now that we have that out of the way, lets clean up your code a whole bunch. First, since you are using async
, you should almost never need to use new Promise
. Marking the function as async
implicitly wraps whatever it returns in a promise, meaning you don't need to.
// NOTE: I've removed your console.log statements to make it simpler to read
async function getInterval(climatedata,harvestdate,period) {
return getDate(harvestdate,-1*period).then((sval)=>{
let start = sval.getTime();
getDate(harvestdate,0).then(async(eval)=>{
let end = eval.getTime();
let filtered = await Promise.all(climatedata.filter((curVal,index,arr) => {
return getDate(curVal[0]).then((tval)=>{ // NOTICE: I added `return` here to beging to fix your filter problem
let td = tval.getTime();
if(td >= start && td <= end) {
return true;
} else {
return false;
}
}).catch((err)=>{console.log(err);});
}));
return filtered;
});
});
}
Ok, next, since you're in async
world, you never need to use .then
or .catch
:
async function getInterval(climatedata, harvestdate, period) {
let sval;
try {
sval = await getDate(harvestdate, -1 * period);
} catch (error) {
console.log('getting `sval` failed, oh no!');
throw error;
}
let start = sval.getTime();
let eval;
try {
eval = await getDate(harvestdate, 0);
} catch (error) {
console.log('getting `eval` failed, oh no!');
throw error;
}
let end = eval.getTime();
let filtered = await Promise.all(climatedata.filter(async (curVal,index,arr) => {
let tval;
try {
tval = getDate(curVal[0]);
} catch (error) {
console.log('getting `tval` failed, oh no!');
throw error;
}
let td = tval.getTime();
if(td >= start && td <= end) {
return true;
} else {
return false;
}
}));
return filtered;
}
So much nicer. But ok, let's get to the meat of your issue again: you want to filter a list of promises down. That means you can't only use filter
, you need to use filter
and map
:
async function getInterval(climatedata, harvestdate, period) {
let sval;
try {
sval = await getDate(harvestdate, -1 * period);
} catch (error) {
console.log('getting `sval` failed, oh no!');
throw error;
}
let start = sval.getTime();
let eval;
try {
eval = await getDate(harvestdate, 0);
} catch (error) {
console.log('getting `eval` failed, oh no!');
throw error;
}
let end = eval.getTime();
const filterTest = (curVal, index, arr)
const climatedataPromises = climatedata.map(curVal => getDate(curVal[0])); // Create a list of promises
const climatedata = await Promise.all(climatedataPromises); // Wait for them all to return
return climatedata.filter((tval, index) => { // Now run your filter
let td = tval.getTime();
if(td >= start && td <= end) {
return true;
} else {
return false;
}
});
}
Enjoy :)
*I don't promise that I'm not missing a closing paren or bracket in there somewhere :)
Upvotes: 5