繁体   English   中英

Firefox WebExtensions browser.tabs.query()返回的不可访问数组。 有人可以解释为什么吗?

[英]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 { … }    

是什么赋予了? 为什么我可以从控制台访问数组的元素,但不能从代码访问?

如您所见,固定的数组已填充,但我无法使用该数组访问其中的各个元素。 有人知道为什么会这样吗?

这实际上是异步代码和数组引用的问题。 让我们尝试一步一步来看看如何进行:

  1. 您调用browser.tabs.query 它返回一个承诺, 但不能立即解决 因此,你不进入then一部分暂时的,所以执行代码继续到下一部分...
  2. 这是console.debug("All Pinned Tabs", pinned); 您正在记录一个数组,因此您要为console.debug提供对该数组引用 ,这在这里确实很重要。 该引用不会随时间变化:当您声明pinned数组并且脚本结束时,该数组引用仍将相同。
  3. 然后,您进入console.debug("First Pinned Tab", pinned[0]); 此时,尚未执行Promise处理程序,因此pinned仍然为空,而pinned[0]实际上是undefined 这就是undefined被记录的原因。
  4. 诺言解决:您通过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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM