Javascript ES6生成器异步

时间:2015-05-27 00:25:08

标签: javascript generator ecmascript-6

我需要运行生成器异步(我需要在控制台1,2,3,4,5中导致结果现在我有4,1,2,3,5)任何人都可以帮助我吗?我需要运行任务并等待上一个任务完成后再运行下一个任务。我需要使用(如果可能的话)发电机(或发电机+承诺?)

这是我的代码

/*jshint esnext: true */
function show(msg) {
  var _msg = msg;
  setTimeout(function() { console.log(_msg);}, 2000);
}

function show2(msg) {
  console.log(msg);
}

var stack = [];

// add some function to stack
stack.push(function() { show(1); });
stack.push(function() { show(2); });
stack.push(function() { show(3); });
stack.push(function() { show2(4); });
stack.push(function() { show(5); });

function* generator1() {
  for(var key of stack) {
    yield key();
  }
}
var gen = generator1();
gen.next();
gen.next();
gen.next();
gen.next();
gen.next();

3 个答案:

答案 0 :(得分:4)

这可以完全用发电机完成。这是一种方法的示例,其中我们将.next()移动到超时本身,以确保它不会提前发生。此外,生成器现在将函数从堆栈中返回而不是执行它,因为您无法在生成器本身的执行中调用生成器上的.next()

值得注意的是,这可能不是我在野外做到这一点的方式'我包括承诺。但是你问过是否可以用一台发电机来完成 - 答案是“是的”#。

function show(msg) {
  var _msg = msg;
  setTimeout(function() { 
      console.log(_msg);
      execute();
  }, 2000);
}

function show2(msg) {
  console.log(msg);
  execute();
}

var stack = [];

function execute() {
  var fn = gen.next().value;
  if (fn) fn();
}

// add some function to stack
stack.push(function() { show(1); });
stack.push(function() { show(2); });
stack.push(function() { show(3); });
stack.push(function() { show2(4); });
stack.push(function() { show(5); });

function* generator1() {
  for(var key of stack) {
    yield key;
  }
}
var gen = generator1();
execute();

http://jsfiddle.net/smmccrohan/k271gz7o/

答案 1 :(得分:2)

这有很多“任务运行”功能,你甚至可以自己编写。但是你必须使用Promises,而不是function delay (ms, val) { return new Promise(function (res) { setTimeout(res, ms || 1000, val || Math.random()); }); } function* run () { yield delay(); console.log(yield delay()); yield delay(); console.log('foo'); // sync calls anywhere in between console.log(yield delay()); } function async(gen){ "use strict"; gen = gen(); return Promise.resolve().then(function cont(a){ var n = gen.next(a), v = Promise.resolve(n.value); if(n.done) return v; // a `return` return n.value.catch(gen.throw.bind(gen)).then(cont); }); }; async(run);。这是一个简单的例子:

next

基本上,我们调用生成器的next方法,等待它完成,然后再次触发Promise.coroutine方法,并递归直到生成器停止。

Bluebird具有更多防错功能,名为{{1}}。

Task.js:http://taskjs.org/专门为此提供了一个功能。

希望有所帮助!

答案 2 :(得分:1)

您需要一种方法让您的功能告诉它们何时完成。承诺是解决这个问题的好方法。

我会尽可能坚持原始代码:

function show(msg) {
  return new Promise(function(resolve){
    var _msg = msg;
    setTimeout(function() { console.log(_msg); resolve(_msg);}, 2000);
  });
}

function show2(msg) {
  return new Promise(function(resolve){
    console.log(msg);
    resolve(msg);
  });
}

var stack = [];

// add some function to stack
stack.push(function() { return show(1); });
stack.push(function() { return show(2); });
stack.push(function() { return show(3); });
stack.push(function() { return show2(4); });
stack.push(function() { return show(5); });

function* generator1() {
  for(var key of stack) {
    yield key();
  }
}

var gen = generator1();
gen.next().value.then(function(){
  gen.next().value.then(function(){
     gen.next().value.then(function(){
        gen.next().value.then(function(){
           gen.next();
        });
    });
  });
});

当然它看起来很难看,而且可以改进。如其他答案中所述,有任务运行器和流控制库,例如task.jsgen-runco

使用co,最后一部分是:

co(generator1);