As Felix says, a promise is just another value to be yielded.
However, there is a style of writing asynchronous code which makes use of yielded promises in a particular way. This involves a surrounding piece of code which invokes the generator, then waits for the yielded promise to resolve, and then and only then asks the generator for the next value. This allows you to write your programs as:
function goGenerator *() {
var userData = yield getUserData();
yield checkuserData(userData);
}
Where both getUserData
and checkUserData
return a promise. It's a little bit cleaner than having to write
function goPromises() {
return getUserData() . then(checkUserData);
}
especially if there are more promises involved. This generator-based style reads sequentially, and is reminiscent of an async function approach.
async function goAsyncFunction() {
var userData = await getUserData();
return await checkUserData(userData);
}
But async functions are not widely supported yet. The generator-based approach is an alternative which works with pure ES6.
As I mentioned, the generator-based approach requires a piece of code "surrounding" it that knows what to do with the yielded promises--which, as I said, is to wait for them to resolve before calling the the generator again. The classic implementation of this is co
--you can Google that. Or you can write your own:
function spawn(generator) {
var iterator = generator();
return new Promise(
resolve =>
function iterate(val) {
var {value, done} = iterator.next(val);
if (done) { resolve(val); }
else { Promise.resolve(value).then(iterate); }
}()
);
}
Now you run spawn(goGenerator)
. spawn
itself returns a promise, so you can hang more stuff of it: spawn(goGenerator) . then(doMoreStuff)
.
This is a very simple implementation. co
has many more features--for instance, you can yield
an array of promises, and it will wait for all of them to resolve, a la Promise.all
.