4

I'm writing an AWS Lambda function in TypeScript using the Node.js runtime. I'm using a "batchDelete" function from a DynamoDB ORM library which returns an AsyncIterableIterator type.

According to the documentation here https://github.com/awslabs/dynamodb-data-mapper-js#batchDelete, I should invoke the method with a for await loop like this:

for await (const found of mapper.batchDelete(toRemove)) {
    // items will be yielded as they are successfully removed
}

This all works great but the problem comes in where if I enable ESLint on my project. The default rules throw an error because the for await block is empty. I also get a warning because the found constant is never used. I have no use for the found constant and don't want to log it. I was wondering if there was another way to call an AsyncIterableIterator function where we disregard what is returned and don't have the empty block?

Gambit
  • 286
  • 3
  • 8
  • That's a very weird API if you have to iterate it, but don't care about the result of the iteration. That usage doesn't make sense to me. It seems like maybe you should be using `Promise.all()` so you can just know when they are all done if that's all you care about. – jfriend00 Jun 22 '20 at 21:41

1 Answers1

0

If you don't care about the results of the iteration, then you should probably just do something like this:

await Promise.all(toRemove.map(item => mapper.delete(item));

To use the mapper.batchDelete(toRemove) result more directly, you have to allow for multiple levels of promises. Perhaps you could do this:

await Promise.all(await mapper.batchDelete(toRemove)[Symbol.asyncIterator]());

In doing this, await mapper.batchDelete(toRemove)[Symbol.asyncIterator](), that would get you the default async Iterator and then passing it to Promise.all() would iterate it to get an iterable of promises. Unfortunately, in building it to make this easier:

for await (const found of mapper.batchDelete(toRemove))

they made it a bit more difficult to just get an array of promises out of it.

FYI, here's a link to the code for the .batchDelete() method if you want to look at how it's implemented.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks for taking the time to respond to my question. The reason why I didn't originally go with your first suggestion is that it would result in multiple calls to DynamoDB instead of a single BatchWriteItem operation. This is obviously far cheaper than calling the single delete multiple times. I have tried your other suggestion `await mapper.batchDelete(toRemove)[Symbol.iterator]()` but unfortunately it throws the following error: `ERROR=TypeError: this.dataMapper.batchDelete(...)[Symbol.iterator] is not a function` – Gambit Jun 23 '20 at 14:00
  • @Gambit - Are you sure you typed the suggestion correctly because there is no reference at all to `[Symbol.iterator]` in my answer, but that's what you say the error mentions. I use `[Symbol.asyncTterator]`. – jfriend00 Jun 23 '20 at 14:04
  • I had to change from `[Symbol.asyncIterator]` to `[Symbol.iterator]` as I was getting this error `No overload matches this call. The last overload gave the following error. Argument of type 'AsyncIterableIterator' is not assignable to parameter of type 'Iterable'. Property '[Symbol.iterator]' is missing in type 'AsyncIterableIterator' but required in type 'Iterable` – Gambit Jun 23 '20 at 15:00