0

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?

asked Mar 7, 2016 at 7:22
7
  • "My understanding is that if a function returns a Promise, then it can be used with yield." Generators (and yield) have nothing to do with promises. They can be used together to implement something like async/await, but yield itself doesn't treat promises differently from any other value. Commented Mar 7, 2016 at 7:25
  • This should answer your question: What happens when promise is yielded in javascript? Commented Mar 7, 2016 at 7:27
  • @FelixKling thanks ! I was reading this stackoverflow.com/questions/17516952/… when you posted that :) Commented Mar 7, 2016 at 7:29
  • @FelixKling I did a little digging around and changed Q.fcall( ) to co() and it worked. So what does co exactly do? :) Commented Mar 7, 2016 at 7:33
  • @LittleChild as far as I understand co it basically keeps calling passedInGenerator.next() until the {done: true} object is returned or an error occurs. Commented Mar 7, 2016 at 8:02

2 Answers 2

1

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.

answered Mar 7, 2016 at 9:23
Sign up to request clarification or add additional context in comments.

Comments

1

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);
 });
answered Mar 21, 2016 at 16:14

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.