23

Google Chrome の拡張機能を作成 (学習) しています。

console.log()一部のコードをデバッグするために、次のように を挿入しました。

var fourmTabs = new Array();
chrome.tabs.query({}, function (tabs) {
    for (var i = 0; i < tabs.length; i++) {
        fourmTabs[i] = tabs[i];
    }
});
for (var i = 0; i < fourmTabs.length; i++) {
    if (fourmTabs[i] != null)
        window.console.log(fourmTabs[i].url);
    else {
        window.console.log("??" + i);
    }
}

これは非常に単純なコードです。すべてのタブ情報を独自の配列に取得し、いくつかを出力します。

コードが正常に機能するかどうかを確認するために、コードを実行します。問題は次のとおりです。

  • (開発者ツールを介して) ブレークポイントを使用すると、コードは正常に実行されます。
  • ブレークポイントがないと、何も出力されません。

理由はありますか?

4

1 に答える 1

100

問題は次のように簡略化できます。

/*1.*/ var fourmTabs = [];
/*2.*/ chrome.tabs.query({}, function(tabs) {
/*3.*/     fourmTabs[0] = tabs[0];
/*4.*/ });
/*5.*/ console.log(fourmTabs[0]);

fourmTabs5行目に到達すると、配列が(3行目で)更新されることを期待します。メソッドが非同期であるため、
これは間違っています。chrome.tabs.query


非同期の側面の重要性を理解してもらうために、コードおよびストーリーと同じ構造のコードスニペットを示します。

/*1.*/ var rope = null;
/*2.*/ requestRope(function(receivedRope) {
/*3.*/     rope = receivedRope;
/*4.*/ });
/*5.*/ grab(rope);
  • 1行目では、ロープの存在がアナウンスされます。
  • 2〜4行目で、コールバック関数が作成されます。これは、関数によって呼び出される必要がありrequestRopeます。
  • 5行目では、関数を介してロープをつかみgrabます。

が同期的requestRopeに実装されている場合、問題はありませ   ん。「こんにちは、ロープが欲しいです。ロープを入手したら、「コールバック関数を呼び出して」ロープを投げてください。」   彼女:「もちろん」ロープを投げる   あなた:ジャンプしてロープをつかむ-あなたはなんとか反対側に着き、生きています。


非同期requestRopeで実装されている場合、同期として扱うと問題が発生する可能性があります。   あなた:「私にロープを投げてください。」   彼女:「わかりました。見てみましょう...」   あなた:ジャンプしてロープをつかもうとしますロープがないので、あなたは倒れて死にます。   彼女:もちろん、ロープを投げるのは遅すぎます。




これで、非同期実装関数と同期実装関数の違いがわかりました。元の質問を解決してみましょう。

var fourmTabs = new Array();
chrome.tabs.query({}, function (tabs) {
    for (var i = 0; i < tabs.length; i++) {
        fourmTabs[i] = tabs[i];
    }
    // Moved code inside the callback handler
    for (var i = 0; i < fourmTabs.length; i++) {
        if (fourmTabs[i] != null)
           window.console.log(fourmTabs[i].url);
        else {
            window.console.log("??" + i);
        }
    }
});
// <moved code inside callback function of chrome.tabs.query>

ブレークポイントを使用すると、コードが機能します。これは、コードの2番目の部分に到達するまでに、コールバックがすでに呼び出されているためです。

于 2012-07-27T14:23:52.917 に答える