2017-04-04 7 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が解決されているにもかかわらず、利回りから戻ってきます。

ジェネレータ機能でこれを行うことはできますか?

編集:私は、私が何をしようとしていると思います は、ブルーバードのコルーチンのようなものを実装することです:http://bluebirdjs.com/docs/api/promise.coroutine.html

EDIT2:これは私はこの関数を呼び出す方法です:

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

で見つけることができ、使用しているパターンのhere

Aより理解し説明を見つけることができ、元のスニペットよりも少し複雑ですこの関数をテストするコードを表示できますか? 'yield'は、呼び出し元が値を消費するまで関数を停止します。 – trincot

+0

これは 'console.log(" yield from return "); // never get here' @trincot – shinzou

+0

私はそのコードを意味するのではなく、その関数を呼び出すメインコードです。 – trincot

答えて

1

あなたの問題は、ということですあなたはジェネレータ関数を使用する必要はありません。 yieldでは、yieldステートメントの後にコードの実行が停止するため、console.log('return from field')にアクセスすることはありません。イテレータをもう一度呼び出すと、イールドステートメントの後に続きます(次の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');

することができ、再び

を次の関数を呼び出す必要がありますすることができますスニペット、それはまた、約束を実行します。だから、完全なキューが通じているときに通知されるよりも、それはMDN

関連する問題