2017-04-04 48 views
0

我想运行在块了一项功能,它会等待10K的承诺,以解决再继续,我用下面的发生器功能:发生器功能与产量Promise.all()

function* processNodes(nodes, task){ 
    let i; 
    let cnt = 0; 
    let promiseArray = new Array(10000); 
    let pInd = 0; 
    let currId; 

    for(i = 0; i<nodes.length; i++){ 
     currId = nodes[i]; 
     promiseArray[pInd++] = asyncFunc(currId, 0, task); // return a promise 
     cnt++; 

     if(cnt > 10000){ 
     console.log("going to yield", promiseArray) 
     let pall = Promise.all(promiseArray); 
     console.log("promise all", pall); 
     yield pall; 
     console.log("return from yield"); // never get here 
     pInd = cnt = 0; 
     } 
    } 
    } 

但它从来没有即使我看到pall已解决,也会从收益中返回。

是否有可能使用generator函数做这样的事情?

编辑: 我想我正在试图做的是要实现像蓝鸟的协同程序:http://bluebirdjs.com/docs/api/promise.coroutine.html

EDIT2:这是我如何调用该函数:

let x = processNodes(allNodes, someSimpleTask); 
x.next(); 
+0

发现原来片段更复杂你能展示你测试这个函数的代码吗? 'yield'将暂停函数,直到调用者使用该值。 – trincot

+0

这个:'console.log(“return from yield”); //永远不会到达这里@trincot – shinzou

+0

我不是指那个代码,而是调用这个函数的主代码。 – trincot

回答

1

你的问题是,您不应该使用生成器函数。你永远不会去console.log('return from field'),因为在yield,代码在yield语句后停止执行。只有当你再次调用迭代器时,它将在yield语句后继续(直到下一个yield语句)

所以生成器创建一个迭代器,它具有value和布尔标志done。只要做未设置为true,则可以/应该调用一个函数再次

你的代码的简化版本可以是下列

// a very basic async function, just outputting the argument each 5 ms 
 
function asyncFunc(arg) { 
 
    return new Promise(function(resolve) { 
 
    setTimeout(() => { 
 
     console.log(arg); 
 
     resolve(); 
 
    }, 5); 
 
    }); 
 
} 
 

 
// the generator 
 
function* generator(processNodes, task) { 
 
    var limit = 4, 
 
    queue = []; 
 
    for (let i = 0; i < processNodes.length; i++) { 
 
    queue.push(task(processNodes[i])); 
 
    if (queue.length >= limit) { 
 
     yield Promise.all(queue); 
 
     // clears the queue after pushing 
 
     console.log('after queue'); 
 
     queue = []; 
 
    } 
 
    } 
 
    // make sure the receiver gets the full queue :) 
 
    if (queue.length !== 0) { 
 
    yield Promise.all(queue); 
 
    } 
 
} 
 

 
function runThroughArguments(args, task) { 
 
    return new Promise(function(resolve) { 
 
    setTimeout(() => { 
 
     var nodes = generator(args, task), 
 
     iterator = nodes.next(); 
 

 
     if (!iterator.done) { 
 
     // if it's not done, we have to recall the functionallity 
 
     iterator.value.then(function q() { 
 
      setTimeout(() => { 
 
      iterator = nodes.next(); 
 
      if (!iterator.done && iterator.value) { 
 
       // call the named function (in this case called q) which is this function after the promise.all([]) completed 
 
       iterator.value.then(q); 
 
      } else { 
 
       // everything finished and all promises are through 
 
       resolve(); 
 
      } 
 
      }, 2); 
 
     }); 
 
     } else { 
 
     iterator.value.then(resolve); 
 
     } 
 
    }, 2); 
 
    }); 
 
} 
 

 
runThroughArguments(
 
    ['hey', 'you', 'the', 'rock', 'steady', 'crew'], 
 
    asyncFunc).then(() => console.log('completed')); 
 

 
console.log('runs before everything');

在上面片段,它也贯穿承诺。所以,比你能当全队列通过通知,实在是有点除可以找到您所使用的模式here

一个更容易理解的解释可以MDN