I am writing in typescript and I have an object with distinct keys, each mapping to a value. I want to iterate over the keys and do an asynchronous function with their value. I know that you can encase .map (to iterate over arrays) in Promise.all, but how can you do it iterating over a for (let i in object) loop? I'm open to other options that allow all keys to be run concurrently, but waiting on all to complete. Edit: I don't want to use Object.keys because I don't want to iterate over the entire objects keys more than once (Object.keys iterates over the objects keys once, and then I will have to iterate for Promise.all)
Asked
Active
Viewed 1,168 times
1
-
Possible duplicate of [Get array of object's keys](https://stackoverflow.com/questions/8763125/get-array-of-objects-keys) – CertainPerformance Nov 14 '19 at 04:25
-
Take the object's keys (or values or whatever) and map each to a Promise, then you can call `Promise.all` – CertainPerformance Nov 14 '19 at 04:26
-
In terms of performance, the object could be very long and I don't want to turn it into an array then iterate over the array. – Vikram Khemlani Nov 14 '19 at 04:26
-
1You could use `for..in` and push each promise generated from each key to an array, but I'd think that `.map` would be more performant (and, more importantly, much more readable) – CertainPerformance Nov 14 '19 at 04:27
-
Turning each into a promise isn't good for performance since I have to iterate over the entire object, I'm trying to avoid doing so. – Vikram Khemlani Nov 14 '19 at 04:28
-
You say you have to *do an asynchronous function with their value*, so it sounds like there's no avoiding that – CertainPerformance Nov 14 '19 at 04:29
-
I see your point. I thought when you run promise.all, each iteration runs concurrently, but I guess I misunderstood – Vikram Khemlani Nov 14 '19 at 04:30
-
Almost nothing *blocks* by default. Everything will run concurrently unless you explicitly wait for something else to complete first. – CertainPerformance Nov 14 '19 at 04:32
-
Yea, I wanted to wait on all the promises to complete though, so I was using await Promise.all. In terms of mapping each key to a promise, how would I be able to do that? would it just be array['key'] = new Promise(resolve, reject => {}) and then doing promise.all(array)? Something like that? – Vikram Khemlani Nov 14 '19 at 04:34
-
Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/202302/discussion-between-vikram-khemlani-and-certainperformance). – Vikram Khemlani Nov 14 '19 at 04:46
1 Answers
2
Object.entries() can get the keys and values. Collect promises for each key-value pair, and fulfill them with all().
function asyncFunctionWithKeysAndValuesOf(object) {
let promises = Object.entries(object).map(keyValue => somePromiseReturningFn(keyValue[0], keyValue[1]))
return Promise.all(promises)
}
If you're sensitive to iterating the object more than once...
let promises = []
for (key in object) {
promises.push(somePromiseReturningFn(key, object[key]))
}
return Promise.all(promises)
danh
- 59,538
- 10
- 90
- 129
-
Thanks! But I need the keys and the values, and for performance, I didn't want to use Object. because I didn't want to iterate over the object items more than once. – Vikram Khemlani Nov 14 '19 at 04:40
-
1
-
Ok . Object.entries iterates over the object once, which is something I was trying to avoid, as map will iterate over the object again, but I guess O(2n) isn't so bad and I don't see a way around it. Thanks – Vikram Khemlani Nov 14 '19 at 04:44
-
1Agree, @VikramKhemlani, that it's typically fine to loop twice, but we can do just one loop if you prefer. Just not as pretty. See edit. – danh Nov 14 '19 at 04:50
-
Thanks much! Just fairly new and wanted to make as efficient as possible – Vikram Khemlani Nov 14 '19 at 04:55