I am new to the Generator concept. My understanding is that if a function returns a Promise, then it can be used with yield. So I have a very small node.js script that looks like this:
Q.fcall(function*(){
var url = "mongodb://" + config.host + ":" + config.port + "/" + config.db;
var db = yield MongoClient.connect( url );
var data = yield makeRequest();
console.log( data );
db.close();
});
function makeRequest(){
var deferred = Q.defer();
request({
"method" : "GET",
"url" : "....",
"headers" : {
"Accept" : "application/json",
"user_key" : "...."
}
},function(err,data){
if( err ){
deferred.reject( err );
}else{
deferred.resolve( data );
}
});
return deferred.promise;
}
I know this works because I am porting it from the callback hell style to generator style. However, I do not see the data in console.log.
What do I need to change to make this work?
2 Answers 2
Q.fcall is not suited to work with generator functions. You need to use the dedicated generator methods for that, in your case Q.spawn:
Q.spawn(function*() {
var url = "mongodb://" + config.host + ":" + config.port + "/" + config.db;
var db = yield MongoClient.connect( url );
try {
var data = yield makeRequest();
console.log( data );
} finally {
db.close();
}
});
Without a runner, the generator won't be automatically advanced asynchronously.
Comments
Consider using co that can wrap generators and make the callable. It returns promise.
const co = require('co');
const promisedGenerator = co.wrap(function* () {
yield whatever1();
yield whatever2();
return databaseRequest();
});
promisedGenerator()
.then(databaseResult => {
console.log(databaseResult);
});
yield." Generators (andyield) have nothing to do with promises. They can be used together to implement something likeasync/await, butyielditself doesn't treat promises differently from any other value.Q.fcall( )toco()and it worked. So what doescoexactly do? :)coit basically keeps callingpassedInGenerator.next()until the{done: true}object is returned or an error occurs.