Skip to content

Instantly share code, notes, and snippets.

@TiddoLangerak
Created November 9, 2015 10:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TiddoLangerak/0a1b2dd43e8bdc239898 to your computer and use it in GitHub Desktop.
Save TiddoLangerak/0a1b2dd43e8bdc239898 to your computer and use it in GitHub Desktop.
async generators
//Simple, without $await
//In the simple variant $async/yield works like async/await. That is, yield "awaits" a promise,
//and an $async function still returns a promise
const init = $async(function*() {
const user = yield $http.get('/users/me');
$scope.user = user;
const messages = yield messageService.getMessagesFor(user);
$scope.messages = messages;
});
init() //See, it returns a promise
.then(() => console.log('done'));
//Complex, with $await
//In the complex variant $async returns a generator function. This allows for more flexibility,
//but requires a lot more boilerplate.
//Same example:
const init = $asyncGenerator(function*() {
const user = yield $await($http.get('/users/me'));
$scope.user = user;
const messages = yield $await(messageService.getMessagesFor(user));
$scope.messages = messages;
});
//Since it's a generator function we need to kickstart it first, as well as extract the value manually
init().next().value
.then(() => console.log("done"));
//likeley we'll abstract to above into something like this:
$async.run(init())
.then(() => console.log("done"));
//The above example doesn't really seem any better, however it does allow us to do the following (which is awesome!):
const messageGenerator = $asyncGenerator(function*() {
let offset = 0;
const batchSize = 10;
while (true) {
//Yield $async causes the execution of the function to halt until the promise is ready
const messages = yield $async($http.get('messages', { offset, limit : batchSize }));
if (messages.length === 0) {
//No more messages!
return;
}
for (let message of messages) {
//Yield without $async works as a normal yield
yield message;
}
offset += batchSize;
}
});
const fetchNextMessages = $async(function*(amount) {
//Since we can have an async generator we can easily implement rx-like behaviour, where we add each message as it comes in.
const messageStream = yield $stream(messageIterator).fetch(amount);
messageStream
.map((message) => processMessage(message))
.forEach(message => $scope.messages.push(message));
//But we can also still do batch processing as if it where synchronous code:
const messages = yield $await(messageStream);
doStuffWithAllMessages(messages);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment