You are spending too much time waiting for I/O from different sources.
In normal promise code, you’d use Promise.all
for this, however – people have a tendency to write code that waits for requests with generators. Your code does the following:
<-client service->
countryFor..
''--..
''--..
''--.. country server sends response
..--''
..--''
..--''
getCommentDataFor
''--..
''--..
''--..
''--.. comment service returns response
..--''
..--''
..--''
authenticate
''--..
''--..
''--.. authentication service returns
..--''
..--''
..--''
Generator done.
Instead, it should be doing:
<-client service->
countryFor..
commentsFor..''--..
authenticate..''--..''--..
''--..''--..''--.. country server sends response
''--..--''.. comment service returns response
..--''..--''.. authentication service returns response
..--''..--''..
..--''..--''..--''
..--''..--''
..--''
Generator done
Simply put, all your I/O should be done in parallel here.
To fix this, I’d use Promise.props
. Promise.props
takes an objects and waits for all its properties to resolve (if they are promises).
Remember – generators and promises mix and match really well, you simply yield promises:
Client.prototype.fetchCommentData = async(function* (user){
var country = countryService.countryFor(user.ip);
var data = api.getCommentDataFor(user.id);
var notBanned = authServer.authenticate(user.id).then(function(val){
if(!val) throw new AuthenticationError(user.id);
});
return Promise.props({ // wait for all promises to resolve
country : country,
comments : data,
notBanned: notBanned
});
});
This is a very common mistake people make when using generators for the first time.
ascii art shamelessly taken from Q-Connection by Kris Kowal