Reputation: 24565
Currently in our API-server code we have the following:
async someAsyncMethod() {
// ...
let products = await Promise.all(shopStructure.map(async entry => {
try {
const serviceResponse = await this.requestService.someService(entry);
return ProductMapper.map(entry, serviceResponse);
} catch (err) {
this.logger.error('...');
return undefined;
}
}));
products = products.filter(s => s);
return products;
}
How would I use reduce here in order to get rid of the filter operation?
I tried using the following:
async someAsyncMethod() {
// ...
const products = await Promise.all(shopStructure.reduce(async (accumulator, entry) => {
try {
const serviceResponse = await this.requestService.someService(entry);
accumulator.push(ProductMapper.map(entry, serviceResponse));
} catch (err) {
this.logger.error('...');
}
return accumulator;
},[]));
return products;
}
but this results in compile errors ("No overload matches this call", "Argument of type ... is not assignable to parameter of type <never>"
).
Maybe there's another elegant way to do this? Note that I deliberately use Promise.all
instead of for...of
for performance reasons.
Upvotes: 1
Views: 358
Reputation: 370779
I don't think reduce
is the right tool here. You need to wait for n
Promises to resolve, where n
is the length of the shopStructure
; the input array and the array of Promises that Promise.all
needs are one-to-one, so .map
and Promise.all
definitely is the right approach.
You can avoid using .filter
if you want by pushing to an array instead:
async someAsyncMethod() {
const products = [];
await Promise.all(shopStructure.map(entry => (
this.requestService.someService(entry)
.then(serviceResponse => products.push(ProductMapper.map(entry, serviceResponse)))
.catch(err => { this.logger.error('...'); })
)));
return products;
}
I don't think there's a good-looking way to use reduce
, since the .map
is already essential.
Upvotes: 2