Objects as collections - map, some etc.
xixixao opened this issue · 5 comments
What is the best practice for emulating map, some etc. on object values and keys instead of arrays? Possible addition?
While I am asking, it would be nice to provide or point to an explanation of differences (advantages) of deferred over Q.
@xixixao Concerning map
for objects It depends on use case. Can you describe yours?
When I deal with async operations which for some reason I collect in a key/value map I usually don't need to get a result hash with all values resolved, instead I keep it as hash of promises, and work with it that way.
So plain speaking there's no map
for objects as there was no real use case yet to have it.
Concerning deferred over Q comparison. Firstly I don't want to bash Q to much, work of Kris Kowal, was real inspiration for this library, and through his work, I get to really know the concept of promises. Anyway Q in my eyes a bit over theorized and at the time it didn't solve my practical needs. Putting points generally, it would be:
- Big performance difference, Q for various reasons is magnitudes slower and introduces asynchronicity on it's own which makes things slower further. I work with scripts that at some times handle hundreds of async operations at one time, Q would be no go for that. I shown that difference in benchmarks included in the repository.
- Deferred in my eyes provides simpler and more composable API. Technically anything you rewrite from Q to deferred will look cleaner and simpler, good example of that opens main documentation.
- Many core functionalities like
deferred.promisify
orpromise.done
(previously namedpromise.end
) appeared in Q much later. Withoutpromise.done
there's no way to expose unhandled exceptions which otherwise remain silent, andpromisify
is crucial to integrate with Node.js callbacks style. Still even Q's counterpart forpromisify
leaves a lot to desire, it started with two not really composable solutions, now I think they're trying to fix that. - Deferred's codebase is modular, well tested and I believe much more solid. Currently there's no single bug in deferred that I'm aware of, and I use it in really intense stuff.
I'm gonna close this issue for now, but we can keep discussion here (see also deferred group on google).
If you really feel there needs to be some map
counterpart for objects, please explain with valid use case, and reopen. We'll see what's best solution for that.
Thank you for the comparison, very much appreciated.
For the use case (using Q because I came across it first):
db = mongoose.connection
Q.map db.collections, (collection) ->
Q.ninvoke collection, 'drop'
Where Q.map is actually my implementation, like deferred.map (again, before I found out about deferred):
Q.map = (values, callback) ->
if Array.isArray values
Q.all values.map callback
else
Q.all (callback v, k for k, v of values)
Also libraries such as underscore provided iteration for both objects and arrays.
@xixixao thanks, and in that case db.collections
is an array, so you can use deferred.map
without issues.
Have you approached the case where you wanted to use your Q.map
on hash object?
No no, in that case db.collections is a map from name of collections to their objects.
@xixixao ah indeed. I thought they match native driver api.
In such case, I would fallback to lang utitlity of your choice (e.g. underscore) and do:
Collection.prototype.pdrop = deferred.promisify(Collection.prototype.drop);
deferred.map(values(db.collections), function (collection) { return collection.pdrop(); });