2017-10-28 9 views
1

非同期のruipgil/scraperjs関数を使用してスクレーパーを作成しようとしました。しかし、私はそれをループの中に入れると、詰まって動作しません。私はNodeと、非同期プログラミングのアイデアを知っていますので、私に同行してください。whileループ(scraperjs)内で使用すると非同期関数が詰まった

だから、私はこのコードを持っている:

let scraperjs = require('scraperjs'); 

// scraper function 
function scrape(pageURI, callback) { 
    console.log('checkpoint 2'); // checkpoint 
    scraperjs.StaticScraper.create(pageURI).scrape(function($) { 
     console.log('checkpoint 3'); // checkpoint 
     return $("div").map(function() { 
      return $(this).text(); 
     }).get(); 
    }).then(function(sometext) { 
     callback(sometext); 
    }); 
} 

// loop function 
function testloop() { 
    let finished = false; 
    let processed = false; 

    while (!finished) { 
     if (!processed) { 
      console.log('checkpoint 1'); // checkpoint 
      scrape('https://www.google.com/', (sometext) => { 
       console.log('checkpoint 4', sometext); // checkpoint 
       finished = true; 
      }); 
      processed = true; 
     } 
    } 
} 

// non loop function 
function testnonloop() { 
    console.log('checkpoint 1'); // checkpoint 
    scrape('https://www.google.com/', (sometext) => { 
     console.log('checkpoint 4', sometext); // checkpoint 
    }); 
} 

私は完全な4つのチェックポイントの出力を期待して、両方の機能を派遣しようとしました。しかし、不思議なことに、ループのあるものはチェックポイント2で詰まってしまい、決して進まない。 [私もコールバックスタイルの代わりに約束を使ってみましたが、同じ出力です。]

どこが間違っていましたか?

答えて

1

問題は、コールバック関数が実行されることはありません飽きないだろうので、whileループ内の条件は、決して変わらないということです。

JavaScriptプログラムがイベントループで実行されるためです。 JavaScriptエンジンにはコールスタック(プログラムのどこに記録されているか)と(実行する非同期コールバックを追跡する)コールバックキューがあります。

イベントループモニターコールスタックコールバックキュー。コールスタックが空の場合、コールバックキューから最初のイベントを受け取り、実行するコールスタックコールスタックにプッシュします。あなたのケースではコールスタックが空になることはありません

、それは常にwhileループで忙しいですので、コールバックが実行されることはありませんので、while条件は常にtrueです。

setTimeoutを使用すると、最初のコールバックが呼び出されるまでscrapeを呼び出すことができます。 setTimeoutを使用すると、コールスタックを解放し、非同期呼び出しを実行させることができます。

// loop function 
function testloop() { 
    let finished = false; 

    function loop() { 
     if (!finished) { 
      console.log('checkpoint 1'); // checkpoint 
      scrape('https://www.google.com/', (sometext) => { 
       console.log('checkpoint 4', sometext); // checkpoint 
       finished = true; 
      }); 
      setTimeout(loop, 0); 
     } 
    } 
    loop(); 
} 

現在のイベントループのより多くの深さの説明を見つけることができます:How JavaScript works: an overview of the engine, the runtime, and the call stack

+0

ので、基本的に、私は右だ「ターミネーターがasynchronnously悪いながら呼び出しますか」?キューが空になるまで非同期タスクのキューを実行してから消去したい場合、どうすればよいですか? – shrotavre

+0

自分の答えを更新し、ループ中に非同期コードを実行させるサンプルを追加しました。 – ncardeli

1

ループ中に詰まっていないように再帰を試すことができますか?

// loop function 
function testloop() { 
    console.log('checkpoint 1'); // checkpoint 
    scrape('https://www.google.com/', (sometext) => { 
     console.log('checkpoint 4', sometext); // checkpoint 
     testLoop(); 
    }); 
} 
関連する問題