簡體   English   中英

Javascript ES6生成器異步

[英]Javascript ES6 generator async

我需要運行生成器異步(我需要在控制台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();

這可以完全用發電機完成。 下面是一種方法的示例,其中我們將.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/

這有很多“任務運行”功能,你甚至可以編寫自己的功能。 但是你必須為此使用Promises,而不是setTimeout 這是一個簡單的例子:

 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方法,然后遞歸直到生成器停止。

Bluebird有一個名為Promise.coroutine的更多故障保護功能。

Task.js: http ://taskjs.org/專門為此提供了一個功能。

希望有所幫助!

您需要一種方法讓您的功能告訴它們何時完成。 承諾是解決這個問題的好方法。

我會盡可能地堅持原始代碼:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM