2016-12-10 14 views
0

非同期テストを同期的な順序で実行しようとしています。 つまり、各テストはファイルをロードする必要があり、定義上同期しません。代わりに、各テストがファイルをロードし、コードを実行し、次のテストに進み、ファイルをロードするまで待ちます。クロージャがローカル変数を格納していません

問題は非常に奇妙なことですが、私はローカル変数の値をすぐ外に保持しないクロージャを取得します。

このスニペットは大きなライブラリの一部ですので、実行できる自立的な例はあまりありませんが、ここでのロジックはかなり簡単です。

let viewer = ...; 
let tests = [...]; // Let's say the length is 3 

function runTestSync(callback, index) { 
    console.log("FIRST", index) 

    if (index >= tests.length) { 
     callback(index, true); 
    } else { 
     let entry = tests[index]; 

     // Results in files being loaded 
     entry[1](viewer); 

     // Add an event listener to the "viewer" object, which will eventually call the callback when all files finished loading 
     viewer.addEventListener("loadend", function listener() { 
      if (viewer.resourcesLoading === 0) { 
       console.log("SECOND", index); 

       viewer.removeEventListener(listener); 

       callback(index, false); 
      } 
     }); 
    } 
} 

function myIter(index, done) { 
    if (!done) { 
     runTestSync(myIter, index + 1); 
    } 
} 

runTestSync(myIter, 0); 

これは、非同期サーバーフェッチを使用する最もシンプルな同期ループです。 私はあなたが最終的にこれらの行が印刷されなければならないことに同意することができると思う:

FIRST 0 
SECOND 0 
FIRST 1 
SECOND 1 
FIRST 2 
SECOND 2 

代わりにどうなりますか?

FIRST 0 
SECOND 0 
FIRST 1 
SECOND 0 
FIRST 1 
SECOND 0 
FIRST 1 
... 

そして、無限ループが発生します。 indexへの2回目のアクセスが常に0に等しいのはなぜですか?これは、閉鎖が働くはずの方法をはっきりと破っています。

+0

あなたのコードは同じオブジェクトに何度も何度もイベントハンドラを追加します。その「ビューア」が何であるかのコードを見なければ、何が起こっているのかを知るのは難しいことです。 – Pointy

+0

投稿した最初の質問を削除し、この質問からリンクを削除する必要があります。 –

+0

ありがとうございました。私は質問を削除することができません。イベントハンドラはそれ自体を削除するので、一度に1つしか存在しません。ビューアオブジェクトはかなり大きいですが、実際にはこのコードには関係しません。ビューアオブジェクトがファイルを読み込む方法やその間に何をするのかは関係ありません。同じ関数内でローカル変数にアクセスできますそれは同じ関数のクロージャの中にあるとき、突然別の値を持っていますか? – user2503048

答えて

0

削除するリスナーのタイプをviewer.removeEventListener(TYPE, listener)に追加するのを忘れていました。 私は戻ってこない10時間でした。