問題は次のように簡略化できます。
/*1.*/ var fourmTabs = [];
/*2.*/ chrome.tabs.query({}, function(tabs) {
/*3.*/ fourmTabs[0] = tabs[0];
/*4.*/ });
/*5.*/ console.log(fourmTabs[0]);
fourmTabs
5行目に到達すると、配列が(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番目の部分に到達するまでに、コールバックがすでに呼び出されているためです。