ECMA6 生成器:yield promise

新手上路,请多包涵

据我了解,ECMA6 生成器应该能够屈服于返回承诺的函数,最终返回已解决/拒绝的函数。让代码读起来更像同步代码,避免回调地狱。

我将 node.js v0.12.2 与 –harmony 和以下代码一起使用。

 var someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    resolve("I'm Resolved!");
  });
};

someAsyncThing().then(function(res) {console.log(res);});
// Works as expected: logs I'm Resolved!

function* getPromise() {
    var x = yield someAsyncThing();
    console.log("x: " + x); // Fails x undefined
}

var y = getPromise();
console.log(y); // returns {}

console.log(y.next());
// Fails: logs { value: {}, done: false }

我的代码基于我在网上找到的几个例子。我究竟做错了什么?

原文由 Ryhnn 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 564
1 个回答

据我了解,ECMA6 生成器应该能够屈服于返回承诺的函数,最终返回已解决/拒绝的函数。

不,那不是他们的目的。 ES6 生成器应该提供一种编写迭代器的简单方法——每次调用生成器函数都会生成一个迭代器。迭代器只是一系列值 - 就像一个数组,但动态使用并延迟生成。

现在,生成器可以被 滥用 于异步控制流,方法是生成一系列异步使用的承诺,并使用每个等待的承诺的结果推进迭代器。请参阅 此处 以获得没有承诺的解释。

因此,您的代码缺少的是实际等待承诺并推进您的生成器的消费者。通常你会使用一个专用的库(比如 cotask.js ),或者许多 promise 库提供的辅助函数之一( QBluebirdwhen ,……),但为了这个答案的目的,我会展示一个简化一个:

 function run(gf) {
    let g = gf();
    return Promise.resolve(function step(v) {
         var res = g.next(v);
         if (res.done) return res.value;
         return res.value.then(step);
    }());
}

现在有了这个函数,你实际上可以“执行”你的 getPromise 生成器:

 run(getPromise).then(console.log, console.error);

原文由 Bergi 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题