追踪承诺中未捕获的错误
Tracking down an uncaught error in a promise
我正在为 Firefox 编写一个扩展,以允许我从网站上抓取一些数据。
一个简单的描述是该站点包含一个索引页面,其中包含指向包含我想要的数据的子页面的链接列表。我浏览到扩展程序检测到 URL 的索引页面,并询问我是否要抓取它。如果我说是,内容脚本会抓取子页面列表 URLs 并将它们传递给后台进程,后台进程应该在新选项卡中依次打开每个页面,抓取数据,然后关闭选项卡。为了避免服务器出现问题,我设置了一系列超时来创建新选项卡,目前以 10 秒为间隔。
收集完所有数据后,需要将其传递给服务器上的 PHP 脚本,但这超出了本问题的范围。
除了我在控制台上看到打开和关闭的每个选项卡(选项卡编号不同)时出现此消息外,所有这些都按描述工作:
15:06:27.426 Uncaught (in promise) Error: Invalid tab ID: 171
一天中的大部分时间我都对此感到困惑,但我无法找到此错误的根源。这是双重混乱,因为代码完全符合我的要求。
问题:这个错误是从哪里来的,我需要做什么来修复它?
代码如下:
async function backgroundProcess() {
"use strict";
// delay in ms between each new tab. Set to some reasonable value after testing.
const newTabDelay = 5000;
let tabList = [];
let resultList = [];
async function createTab(url, resolve, reject) {
try {
//Create a tab and open the link. Return a promise so that we can wait for everything to complete
let tabId = await browser.tabs.create({url: url});
console.log("executing script in tab " + tabId.id);
let tabData = await browser.tabs.executeScript(
tabId.id,
{
file: 'scrapeMileage.js'
});
console.log("Content script executed");
console.log(tabData);
//resultList.push(tabData);
let tabNumber = tabId.id;
console.log("Removing tab Tab ID " + tabNumber);
await browser.tabs.remove(tabNumber);
console.log("Removed tab Tab ID " + tabNumber);
resolve(tabData);
} catch (e) {
console.log("createTab catch "+e);
reject(e);
}
}
async function tabOpener(linkList) {
try {
console.log("Tab opener now running");
//linkList.forEach((el)=>{console.log("(background) Link found:"+el)});
// Loop through the list opening upo a new tab every few seconds
for (let i = 0; i < Math.min(5, linkList.length); i++) {
console.log("Creating tab for " + linkList[i]);
tabList.push(new Promise((resolve, reject) => {
setTimeout(function () {
createTab(linkList[i], resolve, reject);
}, newTabDelay * i);
}));
}
resultList = await Promise.all(tabList);
console.log("Scraping complete");
console.log(resultList);
} catch (e) {
console.log("tabOpener catch:"+e);
}
}
function listener(message, sender, respond) {
console.log("Received message: "+message.messageType);
console.log(message);
switch (message.messageType) {
case 'mileageData':
break;
case 'scrapeRequest':
console.log("Calling tab opener")
tabOpener(message.data)
break;
}
}
console.log("Setting up message listener");
browser.runtime.onMessage.addListener(listener);
}
console.log("Running background process");
backgroundProcess();
代码中大量添加了 console.log()
以帮助调试。这是控制台输出。
15:05:57.459 Webconsole context has changed
15:05:57.462 Running background process background.js:81:9
15:05:57.463 Setting up message listener background.js:76:13
15:06:05.357 Received message: scrapeRequest background.js:62:17
15:06:05.357
Object { messageType: "scrapeRequest", data: (17) […] }
background.js:63:17
15:06:05.358 Calling tab opener background.js:69:25
15:06:05.358 Tab opener now running background.js:40:21
15:06:05.358 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.359 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.359 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.359 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.359 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.387 executing script in tab 167 background.js:16:21
15:06:06.895 Content script executed background.js:23:21
15:06:06.895
Array [ {…} ]
background.js:24:21
15:06:06.896 Removing tab Tab ID 167 background.js:27:21
15:06:06.905 Removed tab Tab ID 167 background.js:29:21
15:06:06.906 Uncaught (in promise) Error: Invalid tab ID: 167 undefined
15:06:10.371 executing script in tab 168 background.js:16:21
15:06:11.451 Content script executed background.js:23:21
15:06:11.451
Array [ {…} ]
background.js:24:21
15:06:11.452 Removing tab Tab ID 168 background.js:27:21
15:06:11.461 Removed tab Tab ID 168 background.js:29:21
15:06:11.461 Uncaught (in promise) Error: Invalid tab ID: 168 undefined
15:06:15.372 executing script in tab 169 background.js:16:21
15:06:16.751 Content script executed background.js:23:21
15:06:16.751
Array [ {…} ]
background.js:24:21
15:06:16.752 Removing tab Tab ID 169 background.js:27:21
15:06:16.762 Removed tab Tab ID 169 background.js:29:21
15:06:16.765 Uncaught (in promise) Error: Invalid tab ID: 169 undefined
15:06:20.385 executing script in tab 170 background.js:16:21
15:06:21.481 Content script executed background.js:23:21
15:06:21.481
Array [ {…} ]
background.js:24:21
15:06:21.482 Removing tab Tab ID 170 background.js:27:21
15:06:21.489 Removed tab Tab ID 170 background.js:29:21
15:06:21.490 Uncaught (in promise) Error: Invalid tab ID: 170 undefined
15:06:25.382 executing script in tab 171 background.js:16:21
15:06:27.414 Content script executed background.js:23:21
15:06:27.414
Array [ {…} ]
background.js:24:21
15:06:27.414 Removing tab Tab ID 171 background.js:27:21
15:06:27.423 Removed tab Tab ID 171 background.js:29:21
15:06:27.423 Scraping complete background.js:53:21
15:06:27.423
Array(5) [ (1) […], (1) […], (1) […], (1) […], (1) […] ]
background.js:54:21
15:06:27.426 Uncaught (in promise) Error: Invalid tab ID: 171 undefined
一些注意事项:
scrapeMileage.js
脚本目前除了 return 一个固定值外什么都不做。
- 数据是与我有关的数据,仅出于我的目的而检索。一旦这个工作正常,我希望只抓取每个页面一次。
- 出于隐私原因,我混淆了实际涉及的 URL。
从完整日志来看,错误肯定是browser.tabs.remove产生的。事实上,运行 它在 devtools 控制台中手动使用不存在的选项卡 ID 将产生相同的错误消息。例如,如果其他东西已经关闭了选项卡,就会发生这种情况。
这个错误在异步代码中被标准 try/catch 简单地拦截了,就像你已经做的一样。如果您的代码没有拦截此错误,我看到的唯一解释是 Firefox 中的错误或 browser
的不正确的 polyfill。在 Firefox 中不需要这个 polyfill。
我正在为 Firefox 编写一个扩展,以允许我从网站上抓取一些数据。
一个简单的描述是该站点包含一个索引页面,其中包含指向包含我想要的数据的子页面的链接列表。我浏览到扩展程序检测到 URL 的索引页面,并询问我是否要抓取它。如果我说是,内容脚本会抓取子页面列表 URLs 并将它们传递给后台进程,后台进程应该在新选项卡中依次打开每个页面,抓取数据,然后关闭选项卡。为了避免服务器出现问题,我设置了一系列超时来创建新选项卡,目前以 10 秒为间隔。
收集完所有数据后,需要将其传递给服务器上的 PHP 脚本,但这超出了本问题的范围。
除了我在控制台上看到打开和关闭的每个选项卡(选项卡编号不同)时出现此消息外,所有这些都按描述工作:
15:06:27.426 Uncaught (in promise) Error: Invalid tab ID: 171
一天中的大部分时间我都对此感到困惑,但我无法找到此错误的根源。这是双重混乱,因为代码完全符合我的要求。
问题:这个错误是从哪里来的,我需要做什么来修复它?
代码如下:
async function backgroundProcess() {
"use strict";
// delay in ms between each new tab. Set to some reasonable value after testing.
const newTabDelay = 5000;
let tabList = [];
let resultList = [];
async function createTab(url, resolve, reject) {
try {
//Create a tab and open the link. Return a promise so that we can wait for everything to complete
let tabId = await browser.tabs.create({url: url});
console.log("executing script in tab " + tabId.id);
let tabData = await browser.tabs.executeScript(
tabId.id,
{
file: 'scrapeMileage.js'
});
console.log("Content script executed");
console.log(tabData);
//resultList.push(tabData);
let tabNumber = tabId.id;
console.log("Removing tab Tab ID " + tabNumber);
await browser.tabs.remove(tabNumber);
console.log("Removed tab Tab ID " + tabNumber);
resolve(tabData);
} catch (e) {
console.log("createTab catch "+e);
reject(e);
}
}
async function tabOpener(linkList) {
try {
console.log("Tab opener now running");
//linkList.forEach((el)=>{console.log("(background) Link found:"+el)});
// Loop through the list opening upo a new tab every few seconds
for (let i = 0; i < Math.min(5, linkList.length); i++) {
console.log("Creating tab for " + linkList[i]);
tabList.push(new Promise((resolve, reject) => {
setTimeout(function () {
createTab(linkList[i], resolve, reject);
}, newTabDelay * i);
}));
}
resultList = await Promise.all(tabList);
console.log("Scraping complete");
console.log(resultList);
} catch (e) {
console.log("tabOpener catch:"+e);
}
}
function listener(message, sender, respond) {
console.log("Received message: "+message.messageType);
console.log(message);
switch (message.messageType) {
case 'mileageData':
break;
case 'scrapeRequest':
console.log("Calling tab opener")
tabOpener(message.data)
break;
}
}
console.log("Setting up message listener");
browser.runtime.onMessage.addListener(listener);
}
console.log("Running background process");
backgroundProcess();
代码中大量添加了 console.log()
以帮助调试。这是控制台输出。
15:05:57.459 Webconsole context has changed
15:05:57.462 Running background process background.js:81:9
15:05:57.463 Setting up message listener background.js:76:13
15:06:05.357 Received message: scrapeRequest background.js:62:17
15:06:05.357
Object { messageType: "scrapeRequest", data: (17) […] }
background.js:63:17
15:06:05.358 Calling tab opener background.js:69:25
15:06:05.358 Tab opener now running background.js:40:21
15:06:05.358 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.359 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.359 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.359 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.359 Creating tab for https://drivers.uber.com/p3/payments/trips/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx background.js:45:25
15:06:05.387 executing script in tab 167 background.js:16:21
15:06:06.895 Content script executed background.js:23:21
15:06:06.895
Array [ {…} ]
background.js:24:21
15:06:06.896 Removing tab Tab ID 167 background.js:27:21
15:06:06.905 Removed tab Tab ID 167 background.js:29:21
15:06:06.906 Uncaught (in promise) Error: Invalid tab ID: 167 undefined
15:06:10.371 executing script in tab 168 background.js:16:21
15:06:11.451 Content script executed background.js:23:21
15:06:11.451
Array [ {…} ]
background.js:24:21
15:06:11.452 Removing tab Tab ID 168 background.js:27:21
15:06:11.461 Removed tab Tab ID 168 background.js:29:21
15:06:11.461 Uncaught (in promise) Error: Invalid tab ID: 168 undefined
15:06:15.372 executing script in tab 169 background.js:16:21
15:06:16.751 Content script executed background.js:23:21
15:06:16.751
Array [ {…} ]
background.js:24:21
15:06:16.752 Removing tab Tab ID 169 background.js:27:21
15:06:16.762 Removed tab Tab ID 169 background.js:29:21
15:06:16.765 Uncaught (in promise) Error: Invalid tab ID: 169 undefined
15:06:20.385 executing script in tab 170 background.js:16:21
15:06:21.481 Content script executed background.js:23:21
15:06:21.481
Array [ {…} ]
background.js:24:21
15:06:21.482 Removing tab Tab ID 170 background.js:27:21
15:06:21.489 Removed tab Tab ID 170 background.js:29:21
15:06:21.490 Uncaught (in promise) Error: Invalid tab ID: 170 undefined
15:06:25.382 executing script in tab 171 background.js:16:21
15:06:27.414 Content script executed background.js:23:21
15:06:27.414
Array [ {…} ]
background.js:24:21
15:06:27.414 Removing tab Tab ID 171 background.js:27:21
15:06:27.423 Removed tab Tab ID 171 background.js:29:21
15:06:27.423 Scraping complete background.js:53:21
15:06:27.423
Array(5) [ (1) […], (1) […], (1) […], (1) […], (1) […] ]
background.js:54:21
15:06:27.426 Uncaught (in promise) Error: Invalid tab ID: 171 undefined
一些注意事项:
scrapeMileage.js
脚本目前除了 return 一个固定值外什么都不做。- 数据是与我有关的数据,仅出于我的目的而检索。一旦这个工作正常,我希望只抓取每个页面一次。
- 出于隐私原因,我混淆了实际涉及的 URL。
从完整日志来看,错误肯定是browser.tabs.remove产生的。事实上,运行 它在 devtools 控制台中手动使用不存在的选项卡 ID 将产生相同的错误消息。例如,如果其他东西已经关闭了选项卡,就会发生这种情况。
这个错误在异步代码中被标准 try/catch 简单地拦截了,就像你已经做的一样。如果您的代码没有拦截此错误,我看到的唯一解释是 Firefox 中的错误或 browser
的不正确的 polyfill。在 Firefox 中不需要这个 polyfill。