2017-08-15 13 views
1
Iは、各ノードの処理上から下まで全体DOMをクロールする必要

を使用してループに非同期呼び出しを行うクライアントから生成関数を呼び出します。あるノードが特定の基準を満たしている場合、そのノードに関する情報を同期して処理する必要があります。つまり、処理が完了するまでDOMの次のノードに進むことはありません。は約束

ノードの処理は、複数のAjaxの呼び出しを必要とし、私は非同期的にこれらの呼び出しを実行したいと思います。すべてのAjax呼び出しが完了した後でのみ、最終的な処理作業が完了し、結果がDOMクロールのポイントに戻されます。

私が注目している解決策は、DOMのクロールを行い、基準を持つノードが満たされ、そのノードの内容がクライアントに戻されたときにyield文を実行するジェネレータ関数を作成することです(yield文を介して)次の関数を呼び出す。

その後、ノードのデータを解析し、複数の約束を作成して、Promise.allと非同期に、すべてのこれらの約束を実行しますジェネレータ関数の呼び出しを開始したクライアント()。

すべての約束が完了して処理が終了すると、ジェネレータ関数が再度呼び出されますが、今回はクライアントからの処理済データがyield文の途中に返され、これがDOMにマージされます。私には明らかではないが、何

は約束を実行することを含むノードの処理を実行するクライアントコードを作成する方法です。可能であれば、私は再帰的にクライアント関数を呼び出すことを避けたいと思います。

ジェネレータ::ここで私が行われて想像することができるいくつかの擬似コードである

function *crawlDOM() { 
    let node = "html"; 

    function processNode(node) { 
    if (node.value == "someCriteria") { 
     let processedValue = yield node.value; 
     // Do something with the processed value... 
    } 

    for (let i = 0; i < node.children.length; i++) { 
     processNode(node.children[i]); 
    } 
    } 
} 

ノード処理クライアント:私はループ問題を解決するにはどうすればよい

function processNodeData() { 
    var crawler = crawlDOM(); 
    var processedData = ""; 

    while (true) { 
     var nodeData = crawler.next(processedData).value; 
     var items[] = nodeData.split("\n"); 
     var promises[] = [items.length]; 

     for (let i = 0; i < items.length; i++) { 
      promises[i] = new Promise(function (resolve, reject) { 
      // Do some work 
      resolve(result); 
      } 
     } 

     Promises.all(promises) 
     .then(function(result) { 
      processedData = "some new data"; 
      // Do some final processing. 
      // At this point, we need to call the generator function again but with the processed data. 
      // But this is the wrong place to do it because the "while" loop will have already moved on 
      // to the next node while this "then" code is being executed. 
     }) 

    } 
} 

ように発電機の次の呼び出し関数はPromise.all()が完了した後にのみ発生します。

+0

ノードを使用していますか?そこにきちんとしたlibがあります、 'npm install co' GHリポジトリはこちらです..ご覧ください=> https://github.com/tj/co –

+0

@KresimirPendicリンクをありがとう、そのコードは古くなって見えませんほぼ1年間でコミットする。私が下に出てきた解決策はかなりシンプルで、問題を解決します。 – AndroidDev

答えて

0

ループに約束を実行するための鍵は、非同期関数内これらの約束を配置することである:コードの

function processNode(x) { 
    return new Promise(resolve => { 
     setTimeout(() => { 
      resolve(x); 
     }, 2000); 
    }); 
} 

async function startNodeProcessing() { 
    while(true) { 
     var a = processNode(20); 
     var b = processNode(30); 
     var r = await a + await b; 
    } 

    return; 
} 
startNodeProcessing(); 

線はすべて約束まで

var r = await a + await b; 

ブロックが完了しました。つまり、Promise.allは必要ありませんが、おそらくそれを使用することはできます。ブロックが完了したら、ループを繰り返すことができます。そこには、再帰呼び出しはありませんブロッキングは、メインスレッドをブロックしていないことを意味非同期機能にネイティブなので、あなたが処理するために、ループで長いコードを持っている場合は、任意のUIの問題は表示されません。