Promise.coroutine如何支持生成器作为yieldable值?

Promise.coroutine支持Promise作为可产生的值types。 通过addYieldHandler(function handler)Promise.coroutine也可以支持任何只能重新返回结果的types。 但我怎么能写一个yieldHandler,可以像co一样处理一个generatortypes呢?

首先,蓝鸟协同程序返回的承诺当然是可以自行承担的:

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

通常,一个生成器是一个函数的语法糖,它返回一个可迭代的序列。 它本质上没有什么asynchronous的。 你可以编写在ES5甚至ES3中返回迭代器的代码,并在发生器中以yield使用它。

现在 – 至于你的问题:

我不会推荐使用Promise.coroutine

从你使用的特定迭代产生任意的迭代是容易出错的,在Promise.coroutine中包装它使得它成为一个明确的协程,你可以很容易地产生这个协程。 这是明确的,清楚的,并保留了各种有用的属性。

产生承诺并不是巧合,ES7中的async函数有许多好处。 承诺代表了一个时间价值,他们真的是唯一的等待是有道理的 – 他们正是代表着这个 – 你等待的东西。 出于这个原因 – 明确地等待承诺是有益的,并使得一个坚实的抽象。

如果你想从一个任意的发生器产出 – 你不需要通过蓝鸟添加一个产量处理器。

JavaScript中的生成器已经具有使用特殊符号构build的能力,因此不需要为特定的承诺库添加特定的exception,以便从其他迭代器中生成。

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

如果你想从另一个发生器产出,你可以简单地yield *调用它。 这样就明确了你正在委托。 它只是代码的一个字符,但是它更加明确,并且使用debugging器也更容易,因为引擎知道委派。 我仍然更愿意承诺承诺,但是如果你对此感到强烈的话 – 委托给其他发电机听起来比明确产生发电机要好得多。

请注意,这比产生生成器要快得多,因为Promise.coroutine的转换过程并不便宜,因为它意味着被执行一次,然后被使用,所以转换本身并不快,但它产生了一个非常快的函数(更快几乎所有的使用情况都是async ,而且大多数人在大多数情况下编写加快程序的速度比较快,如果你委派代替每次创build一个协程并运行它,那么你的性能会更好。

如果你坚持,你可以添加addYieldHandler

这是完全可能的。 如果你对速度的惩罚和(在我看来更糟)的抽象是好的。 你可以使用addYieldHandler来产生生成器。

首先,“好”的方式:

 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); }); } }); 

在这里 – 我们增加了生成迭代器而不是生成器的能力,好处是不是生成器的函数(例如 – 来自第三方库),但仍然可以生成迭代器。 上面的用法是: yield generatorFn()你调用生成器的地方。 请注意,我们的代码复制了Promise.coroutine实际做的事情,而且我们几乎结束了它的一个“本地”实现。

现在,如果你想产生发电机 ,你仍然可以这样做:

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

这是为了完整,尽pipe:)