[英]Inaccessible array returned by Firefox WebExtensions browser.tabs.query(). Can someone explain why?
有人可以告訴我這是怎么回事嗎? 我正在使用Firefox WebExtensions API,並且遇到了一些非常奇怪的行為。 這是一些非常簡單的代碼來說明問題。
我正在查詢所有窗口中的所有固定選項卡,並且期望全局數組var pinned = [];
將使用標簽數據/對象填充。 但是,至少可以說這有點棘手。 該數組似乎已填充,但使用標准數組符號pinned[0]
不能訪問undefined
無法訪問各個元素。 我對此感到非常困惑。
那么這是怎么回事? 這是有關范圍或權限的問題嗎?
現在的代碼...
[manifest.json]
{
"manifest_version": 2,
"name": "test",
"version": "1.0",
"description": "test",
"icons": {
"48": "icons/page-48_white.png"
},
"permissions": [
"tabs",
"<all_urls>"
],
"background": {
"scripts": ["background.js"]
},
"devtools_page": "test.html",
"browser_action": {
"default_icon": { "48": "icons/page-48_white.png"},
"default_title": "Test",
"browser_style": true
}
}
[background.js]
function createExtPage(){
browser.tabs.create({ "url": "test.html" });
}
browser.browserAction.onClicked.addListener(createExtPage);
[test.js]
var pinned = [];
browser.tabs.query({pinned: true})
.then(tabs => {
for (let [key, value] of tabs.entries() ) {
console.log("Object " + key, value);
pinned.push(value);
}
});
console.debug("All Pinned Tabs", pinned);
console.debug("First Pinned Tab", pinned[0]);
現在來看一下Firefox開發者工具控制台的輸出。
All Pinned Tabs
[]
0: {…}
active: false
audible: false
discarded: false
favIconUrl: "http://www.crunchyroll.com/favicon.ico?v=1"
height: 800
hidden: false
highlighted: false
id: 149
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522229700160
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Crunchyroll - Watch Naruto Shippuden, Bleach, Anime Videos and Episodes Free Online"
url: "http://www.crunchyroll.com/"
width: 1440
windowId: 3
__proto__: Object { … }
1: {…}
active: false
audible: false
discarded: false
favIconUrl: "https://www.pandora.com/favicon.ico"
height: 800
hidden: false
highlighted: false
id: 145
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522447564848
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "All Along The Watchtower Radio - Now Playing on Pandora"
url: "https://www.pandora.com/station/play/3395036678172411653"
width: 1440
windowId: 67
__proto__: Object { … }
2: {…}
active: false
audible: false
discarded: false
height: 800
hidden: false
highlighted: false
id: 171
incognito: false
index: 1
isArticle: false
isInReaderMode: false
lastAccessed: 1522398347238
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Debugging with Firefox Developer Tools"
url: "about:debugging"
width: 1440
windowId: 67
__proto__: Object { … }
length: 3
__proto__: Array []
First Pinned Tab undefined
Object 0
{…}
active: false
audible: false
discarded: false
favIconUrl: "http://www.crunchyroll.com/favicon.ico?v=1"
height: 800
hidden: false
highlighted: false
id: 149
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522229700160
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Crunchyroll - Watch Naruto Shippuden, Bleach, Anime Videos and Episodes Free Online"
url: "http://www.crunchyroll.com/"
width: 1440
windowId: 3
__proto__: Object { … }
Object 1
{…}
active: false
audible: false
discarded: false
favIconUrl: "https://www.pandora.com/favicon.ico"
height: 800
hidden: false
highlighted: false
id: 145
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522447564848
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "All Along The Watchtower Radio - Now Playing on Pandora"
url: "https://www.pandora.com/station/play/3395036678172411653"
width: 1440
windowId: 67
__proto__: Object { … }
Object 2
{…}
active: false
audible: false
discarded: false
height: 800
hidden: false
highlighted: false
id: 171
incognito: false
index: 1
isArticle: false
isInReaderMode: false
lastAccessed: 1522398347238
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Debugging with Firefox Developer Tools"
url: "about:debugging"
width: 1440
windowId: 67
__proto__: Object { … }
這是真正棘手的事情。 如果我在firefox開發人員工具控制台中鍵入pinned[0]
,我將得到此結果
pinned[0]
{…}
active: false
audible: false
discarded: false
favIconUrl: "http://www.crunchyroll.com/favicon.ico?v=1"
height: 800
hidden: false
highlighted: false
id: 149
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522229700160
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Crunchyroll - Watch Naruto Shippuden, Bleach, Anime Videos and Episodes Free Online"
url: "http://www.crunchyroll.com/"
width: 1440
windowId: 3
__proto__: Object { … }
是什么賦予了? 為什么我可以從控制台訪問數組的元素,但不能從代碼訪問?
如您所見,固定的數組已填充,但我無法使用該數組訪問其中的各個元素。 有人知道為什么會這樣嗎?
這實際上是異步代碼和數組引用的問題。 讓我們嘗試一步一步來看看如何進行:
browser.tabs.query
。 它返回一個承諾, 但不能立即解決 。 因此,你不進入then
一部分暫時的,所以執行代碼繼續到下一部分... console.debug("All Pinned Tabs", pinned);
。 您正在記錄一個數組,因此您要為console.debug
提供對該數組的引用 ,這在這里確實很重要。 該引用不會隨時間變化:當您聲明pinned
數組並且腳本結束時,該數組引用仍將相同。 console.debug("First Pinned Tab", pinned[0]);
。 此時,尚未執行Promise處理程序,因此pinned
仍然為空,而pinned[0]
實際上是undefined
。 這就是undefined
被記錄的原因。 then
處理程序,將tabs列表作為參數接收, then
將tabs推入pinned
數組。 記住,您的第一個console.debug
基於數組引用記錄了該數組,該記錄沒有隨着時間的推移而改變 。 之后,當您在控制台中查看陣列時,此陣列已被填充,您在控制台中訪問的是處於最終狀態的陣列。 這就是為什么整個數組的日志確實會打印數組本身的原因。
...進行一些測試:在第2步,而不是記錄pinned
數組本身,讓我們記錄當前在pinned
的所有元素的id
。
var pinned = [];
browser.tabs.query({pinned: true})
.then(tabs => {
for (let [key, value] of tabs.entries() ) {
console.log("Object " + key, value);
pinned.push(value);
}
});
// will log an empty array since pinned tab is still empty,
// therefore, mapping tab ids will return an empty array
console.warn("All Pinned Tabs", pinned.map((t) => t.id));
// still undefined, nothing changed here
console.warn("First Pinned Tab", pinned[0]);
這是您應該得到的:
All Pinned Tabs : Array []
First Pinned Tab undefined
一種解決方案是在第一個promise的末尾鏈接另一個promise (之所以成為可能,因為每個then
處理程序都返回一個新的promise,因此您可以鏈接它們) ,如下所示:
var pinned = [];
browser.tabs.query({pinned: true})
.then(tabs => {
for (let [key, value] of tabs.entries() ) {
console.log("Object " + key, value);
pinned.push(value);
}
}).then( () => {
// ✓ [1,4,3,2] or anything matching your tabs ids
console.debug("All Pinned Tabs", pinned.map((t) => t.id));
// ✓ First tab object: { ... }
console.debug("First Pinned Tab", pinned[0]);
});
現在您確實獲得了預期的結果:
All Pinned Tabs Array(4) [ 1, 4, 3, 2 ]
First Pinned Tab Object { id: 1, index: 0, windowId: 3, highlighted: false … }
請注意,您可以使第一個Promise返回一個數組,該數組將作為第二個Promise的參數,而不是為數組操作全局變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.