调用chrome.tabs.query后,结果不可用

sam*_*amy 21 javascript asynchronous breakpoints google-chrome-extension google-chrome-devtools

我正在创建(学习)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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是非常简单的代码:将所有选项卡信息放入我自己的数组中,并打印一些东西.

要检查代码是否正常工作,我运行代码.问题出现了:

  • 当我使用断点(通过开发人员工具)时,代码运行正常.
  • 没有断点,不会打印任何内容.

知道为什么吗?

Rob*_*b W 89

您的问题可以简化为:

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

您希望在fourmTabs到达第5行时更新阵列(第3行).
这是错误的,因为该chrome.tabs.query方法是异步的.


为了让您了解异步方面的重要性,我展示了一个代码片段,其结构与您的代码故事相同.

/*1.*/ var rope = null;
/*2.*/ requestRope(function(receivedRope) {
/*3.*/     rope = receivedRope;
/*4.*/ });
/*5.*/ grab(rope);
Run Code Online (Sandbox Code Playgroud)
  • 在第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>
Run Code Online (Sandbox Code Playgroud)

使用断点,您的代码可以工作,因为到达代码的第二部分时,已经调用了回调.

  • 这个答案很有传奇色彩! (10认同)
  • @samy在收到绳子后简单地跳*.必须将"跳转逻辑"附加到回调函数.我已经在答案的最后为你的案例添加了代码,我希望你现在明白了:) (4认同)
  • Stackoverflow上最好的答案之一. (3认同)
  • 哦,我现在看到了差异.现在我知道了!非常感谢!!花时间让我理解这个话题:) (2认同)
  • 甚至两年后答案仍然是传奇...等等... *** (2认同)
  • @GregB回调或承诺. (2认同)