How is the Promise.coroutine support generator valid?

Promise.coroutine supports Promise as a return type. And through addYieldHandler(function handler) , Promise.coroutine can also support any types that reconfigure the result only once. But how can I write yieldHandler that can handle a generator type like co ?

+7
coroutine promise bluebird
source share
1 answer

First of all, Bluebird coroutines return promises, which, of course, can be obtained independently:

 var foo = Promise.coroutine(function*(){ yield Promise.delay(3000); }); var bar = Promise.coroutine(function*(){ yield foo(); // you can do this. }); 

Typically, a generator is syntactic sugar for a function that returns an iterable sequence. There is nothing asynchronous in nature. You can write code that returns iterations in ES5 and even ES3 and consumes it using yield in the generator.

Now - regarding your question:

I would not recommend using Promise.coroutine like this.

Multiplying arbitrary iterations from the particular iterative use that you use is error prone, where packing it in Promise.coroutine makes it an explicit coroutine that you can easily get. It is explicit, clear and retains all sorts of useful properties.

The output of promises is not random, and there is a good reason that the async function in ES7 is waiting for promises. promises represent a temporary meaning, and they really are the only thing that awaits, it makes sense - they represent just that - what you are waiting for. For this reason - clearly expecting promises is useful and makes for a solid abstraction.

If you want to get from an arbitrary generator - you do not need to add a lesson handler through Bluebird.

Generators in JavaScript already have this ability built into a special notation; there is no need to add a specific exception to a specific promise library to give way to other iterators.

 function genThreeToFour*(){ yield 3; yield 4; } function genOneToFive*(){ yield 1; yield 2; yield * genThreeToFour(); // note the *, delegate to another sequence yield 5; } 

The output from another sequence is already built into the generators, if you want to get from another generator, you can just call yield * . So you are explicitly delegating. This is just one more character of the code, but it is much more explicit, and it is also easier to switch to debuggers, since the engine knows about delegation. I still prefer to give only promises, but if you really feel it, delegating to other generators sounds much better than giving generators explicitly.

Note that this is also much faster than getting the generators explicitly, because the Promise.coroutine conversion Promise.coroutine not cheap, because it is designed to be run once, and then used so that the conversion is not fast, but it produces very fast (faster, than async almost all cases of use, and faster than most people write callacks in most cases of use.If you delegate instead of creating a coroutine every time and run it, you will get better performance.

If you insist, you can addYieldHandler

It is quite possible. If you're okay with a speed penalty and (in my opinion, worse) abstraction. You can use addYieldHandler to enable the generation of generators.

First, the “good” way:

 Promise.coroutine.addYieldHandler(function(gen) { if (gen && gen.next && gen.next.call ){ // has a next which is a function return Promise.try(function cont(a){ var n = gen.next(a); if(n.done) return n.value; // `return` in generator if(!n.value.then) return cont(n.value); // yield plain value // handle promise case, propagate errors, and continue return n.value.catch(gen.throw.bind(gen)).then(cont); }); } }); 

Here we added the ability to output iterations, rather than generators, the advantage is that functions that are not generators (for example, from third-party libraries), but still iterate, can still be obtained. Using the above is something like: yield generatorFn() , where you call the generator. Please note that our code here reproduces what Promise.coroutine actually does, and we are almost done with its “own” implementation.

Now, if you want to get generators, you can still do this:

 var Gen = (function*(){}).constructor; Promise.coroutine.addYieldHandler(function(gen) { if (gen && (gen instanceof Gen)){ // detect explicit generator return Promise.coroutine(gen)(); } }); 

This is for the sake of completeness :)

+26
source share

All Articles