Ben*_*aum 26
首先,Bluebird coroutines返回的承诺当然是可以自己屈服的:
var foo = Promise.coroutine(function*(){
yield Promise.delay(3000);
});
var bar = Promise.coroutine(function*(){
yield foo(); // you can do this.
});
Run Code Online (Sandbox Code Playgroud)
通常,生成器是用于返回可迭代序列的函数的语法糖.在性质上没有任何异步.您可以编写在ES5甚至ES3中返回迭代的代码,并yield在生成器中使用它.
现在 - 至于你的问题:
Promise.coroutine像这样使用.从你正在使用的特定迭代中产生任意迭代是容易出错的,其中包装它Promise.coroutine使它成为一个你可以轻易产生的显式协程.这是明确的,清晰的,并保留了各种有用的属性.
屈服承诺并非偶然,并且有充分理由认为asyncES7 中的功能等待承诺.承诺代表了一种时间价值,它们确实是唯一有意义的东西 - 它们恰恰代表了 - 你等待的东西.出于这个原因 - 明确地等待承诺是有益的,并且可以实现可靠的抽象.
JavaScript中的生成器已经具有使用特殊表示法构建的能力,不需要为特定的promise库添加特定的异常,以便从其他迭代中产生.
function genThreeToFour*(){
yield 3;
yield 4;
}
function genOneToFive*(){
yield 1;
yield 2;
yield * genThreeToFour(); // note the *, delegate to another sequence
yield 5;
}
Run Code Online (Sandbox Code Playgroud)
从另一个序列中产生已经内置到生成器中,如果你想从另一个生成器中产生,你可以简单地yield *调用它.这样就明确了你的委托.它只是代码中的另一个字符,但它更明确,并且由于引擎知道委托,因此更容易使用调试器.我仍然更喜欢只承诺承诺,但如果你对此有强烈的感觉 - 委托给其他发电机听起来比明确地让发电机好.
请注意,这也比显式生成生成器快得多,因为转换过程Promise.coroutine并不便宜,因为它意味着执行一次然后使用,因此转换本身并不快但它产生的功能非常快(比async几乎快)所有用例,比大多数用户在大多数用例中编写callack的速度要快.如果你委托而不是每次都创建一个coroutine并运行它 - 你将获得更好的性能.
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);
});
}
});
Run Code Online (Sandbox Code Playgroud)
在这里 - 我们添加了产生迭代而不是生成器的能力,优点是不是生成器的函数(例如 - 来自第三方库)但仍然产生可迭代的函数仍然可以产生.上面的用法是这样的: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)();
}
});
Run Code Online (Sandbox Code Playgroud)
这是为了完整,但:)