What happens when promise is yielded in javascript

2020-01-29 12:25发布

问题:

Didn't find full answer ..

What happens when promise is yielded?

Is such construction

var p = new Promise()
p.resolve(value)

function * (){
  yield p
}

equivalent to

function * (){
  yield value
}

?

UPDATE

How to mix different styles of async programming, for example for such framework as koa?

Koa middlewares are working with generators, but there are lots of good packages which are promise-based (sequelize for ex.)

回答1:

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.



回答2:

What happens when promise is yielded?

Nothing special. A promise is just an object. The generator will yield that promise and you can subscribe to it:

var promise = generator().next().value;
promise.then(...);