You can do this only inside generator.
function* queryDB(query) {
// Here is synchrous-like code!
var rows = yield db.collection.find(query);
var sum = 0;
// Use the rows synchrously
for (var x of rows) {
sum += x;
}
return sum;
}
var sumPromise = doM(queryDB('query example'));
sumPromise.then(console.log.bind(console));
See demo (I recommend to play with this and see what it returns in different cases and it will be clear).
And you can't do:
for (var x of db.collection.find(query))
...
Or:
for (var x of queryDB('some query'))
...
It will be like:
for (var x of (new Promise(...)))
...
Your generator / wrapper will return a promise. You can do only then
with it.
And you can not do:
function* queryDB(query) {
db.collection.find(query).then(function(values) {
yield values;
});
}
Explanation of the last:
How compiler will see this code:
function* queryDB(query) {
db.collection.find(query).then(anonymousFunction);
}
And anonymousFunction
is not a generator, so you can't write yield
there. Also, Promise
in then
doesn't expect a generator.
On the other side if you want to use for (var x in queryDB())
compiler expects to return an array from queryDB()
. If your queryDB()
is asynchrous it will return a Promise-like interface.
If you switch to more functional style, you can write:
forEach(queryDB(), function(item) {
// action on item
});
You can do reduce
or map
implementation if you now that your promised value is an array. But in this case you don't need a generator.
doM
implementation:
function doM(gen) {
function step(value) {
var result = gen.next(value);
if (result.done) {
return result.value;
}
return result.value.then(step);
}
return step();
}
Source: Monads in JavaScript.
forEach
implementation:
function forEach(promise, callback) {
return promise.then(function(iterable) {
for (var x of iterable) {
callback(x);
}
});
}