What happens when promise is yielded in javascript?
Asked Answered
E

2

7

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.)

Entebbe answered 26/11, 2015 at 22:29 Comment(1)
The interesting thing is only what is done to the generator that yields promises. There is nothing special about it in itself.Chrisman
W
6

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.

Washburn answered 27/11, 2015 at 3:36 Comment(4)
Thank you for good explanation. i've updated question. The real problem is not how to convert generator to promise, but how to convert promises to generators.Entebbe
Proper Generator-to-Promise Adapter is needed to use generators within promise context.Pontine
I don't understand what you mean by "convert promises to generators". Can you explain in plain English?Washburn
For completeness, see this generator-to-promise adapter. There is also an exception handling aspect to it for consideration.Pontine
P
6

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(...);
Penta answered 26/11, 2015 at 22:37 Comment(0)
W
6

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.

Washburn answered 27/11, 2015 at 3:36 Comment(4)
Thank you for good explanation. i've updated question. The real problem is not how to convert generator to promise, but how to convert promises to generators.Entebbe
Proper Generator-to-Promise Adapter is needed to use generators within promise context.Pontine
I don't understand what you mean by "convert promises to generators". Can you explain in plain English?Washburn
For completeness, see this generator-to-promise adapter. There is also an exception handling aspect to it for consideration.Pontine

© 2022 - 2024 — McMap. All rights reserved.