Chrome 扩展给出了两个错误:Uncaught TypeError 和 Unchecked runtime.lastError
Chrome Extension gives two errors: Uncaught TypeError and Unchecked runtime.lastError
我在构建 Chrome 扩展时遇到两个错误:
错误 1:
Uncaught TypeError: Cannot set properties of null (setting 'onclick')
Context
_generated_background_page.html
Stack Trace
popup.js:3 (anonymous function)
错误 2:
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
Context
_generated_background_page.html
Stack Trace
_generated_background_page.html:0 (anonymous function)
我已经检查了本网站上解决这两个错误的问题,并尝试了其中提供的解决方案,但我仍然面临这两个错误。
我的原码:-
popup.js(对于错误 1,尝试从 onclick
更改为 onClicked
,对于错误 2,尝试将此代码放入 window.onload
)
let populateBtn = document.getElementById('populateBtn');
let textArea = document.getElementById('productList');
populateBtn.onclick = function(element) {
let color = element.target.value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if(!textArea.value)
{
chrome.tabs.executeScript(
tabs[0].id,
{code: 'alert("Please, populate the order list!");'});
return;
}
chrome.tabs.sendMessage(tabs[0].id, {data: textArea.value.replace(/\t/g,'').split("\n")}, function(response) {
});
});
};
background.html(尝试将 <script>
放在 </body>
标记之后以解决错误 1)
<body>
<p>Gina's Bakery Bulk Order</p>
<textarea id="productList"></textarea>
<button id="populateBtn">Create Order</button>
<script src="popup.js"></script>
</body>
app.js(已尝试 chrome.runtime.connect
错误 2)
chrome.runtime.onInstalled.addListener(function() {
});
inject.js(已尝试 chrome.runtime.onConnect.addListener
错误 2)
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
let failed = [];
request.data.forEach(element => { // itterate over all products
if(element.includes('-')){
let data = element.split('-');
let quantity = data[0].toLowerCase().replace("gb", "").trim();
let ID = data[1].trim();
let elementName = 'pid_' + ID.replace(".", "_");
if(document.getElementsByName(elementName).length > 0)
document.getElementsByName(elementName)[0].value = quantity;
else
failed.push("<td>GB-"+ ID +"</td><td>" + quantity + "</td>");
}
});
if(failed.length > 0){
//alert("Order unsuccessful! One or more products are not ordered: " + failed.join(", "));
let modal = document.createElement("div");
modal.setAttribute("id", "failedOrderModal");
modal.setAttribute("style", "position:fixed;width:250px;left:50%;top:100px;background-color:#fff;border-radius:10px;padding:10px;z-index:10000;color:#000;border: 1px solid red;text-align:center;");
let head = document.createElement("h2");
head.innerText = "Order unsuccessful! One or more products were not found!";
modal.appendChild(head);
let table = document.createElement("table");
let tbody = document.createElement("tbody");
table.appendChild(tbody);
let tr = document.createElement("tr");
tr.innerHTML = "<td>ITEM</td><td>QTY</td>";
tbody.appendChild(tr);
failed.forEach(failedItem => {
tr = document.createElement("tr");
tr.innerHTML = failedItem;
tbody.appendChild(tr);
});
modal.appendChild(table);
let closeBtn = document.createElement("button");
closeBtn.setAttribute("type", "button");
closeBtn.innerText = "Close";
closeBtn.onclick = function(){
document.getElementById("failedOrderModal").remove();
}
modal.appendChild(closeBtn);
document.body.appendChild(modal);
}
else
{
alert("All products were successfuly populated!");
}
sendResponse({result: "ok"})
return true;
});
manifest.json
{
"name": "Gina's Bakery Order",
"version": "1.0",
"description": "Helps automate orders from ginas-bakery.com.au",
"permissions": ["activeTab", "declarativeContent", "storage"],
"background": {
"scripts": ["app.js", "popup.js"],
"persistent": false
},
"icons": {
"16": "images/ginas-bakery_16.png",
"32": "images/ginas-bakery_32.png",
"48": "images/ginas-bakery_48.png",
"128": "images/ginas-bakery_128.png"
},
"browser_action": {
"default_popup": "background.html"
},
"content_scripts": [
{
"matches": ["*://www.ginas-bakery.com.au/order/"],
"js": ["inject.js"]
}
],
"manifest_version": 2
}
None 上述解决方案有效。
后台脚本页面是一个不可见的隐藏页面,所以运行宁app.js或popup.js这样的可见脚本是没有意义的。从 manifest.json 中删除 background
部分,并在磁盘和 manifest.json.
中将 background.html 重命名为 popup.html
manifest.json:
{
"name": "Gina's Bakery Order",
"version": "1.0",
"permissions": ["activeTab", "declarativeContent", "storage"],
"browser_action": {"default_popup": "popup.html"},
"manifest_version": 2
}
仅当页面加载时内容脚本 运行,因此如果您只是重新加载或 installed/updated 扩展而不重新加载选项卡,内容脚本将不会 运行 在那里。
虽然您可以 inject them explicitly,但最好切换到按需编程注入(使用 executeScript 而不是 content_scripts
),因为您可以在安装扩展时不需要任何主机权限就可以做到这一点。
popup.js:
const textArea = document.getElementById('productList');
const btn = document.getElementById('populateBtn');
btn.onclick = () => {
const data = textArea.value.replace(/\t/g, '').split('\n');
chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
chrome.tabs.sendMessage(tab.id, {data}, () => {
if (chrome.runtime.lastError) {
chrome.tabs.executeScript({file: 'inject.js'}, () => {
chrome.tabs.sendMessage(tab.id, {data});
});
}
});
});
};
由于您没有在 sendMessage 中使用响应,因此首先不要发送它,即从 inject.js 中删除 sendResponse({result: "ok"}); return true;
。
我在构建 Chrome 扩展时遇到两个错误:
错误 1:
Uncaught TypeError: Cannot set properties of null (setting 'onclick') Context _generated_background_page.html Stack Trace popup.js:3 (anonymous function)
错误 2:
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist. Context _generated_background_page.html Stack Trace _generated_background_page.html:0 (anonymous function)
我已经检查了本网站上解决这两个错误的问题,并尝试了其中提供的解决方案,但我仍然面临这两个错误。
我的原码:-
popup.js(对于错误 1,尝试从 onclick
更改为 onClicked
,对于错误 2,尝试将此代码放入 window.onload
)
let populateBtn = document.getElementById('populateBtn');
let textArea = document.getElementById('productList');
populateBtn.onclick = function(element) {
let color = element.target.value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if(!textArea.value)
{
chrome.tabs.executeScript(
tabs[0].id,
{code: 'alert("Please, populate the order list!");'});
return;
}
chrome.tabs.sendMessage(tabs[0].id, {data: textArea.value.replace(/\t/g,'').split("\n")}, function(response) {
});
});
};
background.html(尝试将 <script>
放在 </body>
标记之后以解决错误 1)
<body>
<p>Gina's Bakery Bulk Order</p>
<textarea id="productList"></textarea>
<button id="populateBtn">Create Order</button>
<script src="popup.js"></script>
</body>
app.js(已尝试 chrome.runtime.connect
错误 2)
chrome.runtime.onInstalled.addListener(function() {
});
inject.js(已尝试 chrome.runtime.onConnect.addListener
错误 2)
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
let failed = [];
request.data.forEach(element => { // itterate over all products
if(element.includes('-')){
let data = element.split('-');
let quantity = data[0].toLowerCase().replace("gb", "").trim();
let ID = data[1].trim();
let elementName = 'pid_' + ID.replace(".", "_");
if(document.getElementsByName(elementName).length > 0)
document.getElementsByName(elementName)[0].value = quantity;
else
failed.push("<td>GB-"+ ID +"</td><td>" + quantity + "</td>");
}
});
if(failed.length > 0){
//alert("Order unsuccessful! One or more products are not ordered: " + failed.join(", "));
let modal = document.createElement("div");
modal.setAttribute("id", "failedOrderModal");
modal.setAttribute("style", "position:fixed;width:250px;left:50%;top:100px;background-color:#fff;border-radius:10px;padding:10px;z-index:10000;color:#000;border: 1px solid red;text-align:center;");
let head = document.createElement("h2");
head.innerText = "Order unsuccessful! One or more products were not found!";
modal.appendChild(head);
let table = document.createElement("table");
let tbody = document.createElement("tbody");
table.appendChild(tbody);
let tr = document.createElement("tr");
tr.innerHTML = "<td>ITEM</td><td>QTY</td>";
tbody.appendChild(tr);
failed.forEach(failedItem => {
tr = document.createElement("tr");
tr.innerHTML = failedItem;
tbody.appendChild(tr);
});
modal.appendChild(table);
let closeBtn = document.createElement("button");
closeBtn.setAttribute("type", "button");
closeBtn.innerText = "Close";
closeBtn.onclick = function(){
document.getElementById("failedOrderModal").remove();
}
modal.appendChild(closeBtn);
document.body.appendChild(modal);
}
else
{
alert("All products were successfuly populated!");
}
sendResponse({result: "ok"})
return true;
});
manifest.json
{
"name": "Gina's Bakery Order",
"version": "1.0",
"description": "Helps automate orders from ginas-bakery.com.au",
"permissions": ["activeTab", "declarativeContent", "storage"],
"background": {
"scripts": ["app.js", "popup.js"],
"persistent": false
},
"icons": {
"16": "images/ginas-bakery_16.png",
"32": "images/ginas-bakery_32.png",
"48": "images/ginas-bakery_48.png",
"128": "images/ginas-bakery_128.png"
},
"browser_action": {
"default_popup": "background.html"
},
"content_scripts": [
{
"matches": ["*://www.ginas-bakery.com.au/order/"],
"js": ["inject.js"]
}
],
"manifest_version": 2
}
None 上述解决方案有效。
后台脚本页面是一个不可见的隐藏页面,所以运行宁app.js或popup.js这样的可见脚本是没有意义的。从 manifest.json 中删除 background
部分,并在磁盘和 manifest.json.
manifest.json:
{
"name": "Gina's Bakery Order",
"version": "1.0",
"permissions": ["activeTab", "declarativeContent", "storage"],
"browser_action": {"default_popup": "popup.html"},
"manifest_version": 2
}
仅当页面加载时内容脚本 运行,因此如果您只是重新加载或 installed/updated 扩展而不重新加载选项卡,内容脚本将不会 运行 在那里。
虽然您可以 inject them explicitly,但最好切换到按需编程注入(使用 executeScript 而不是 content_scripts
),因为您可以在安装扩展时不需要任何主机权限就可以做到这一点。
popup.js:
const textArea = document.getElementById('productList');
const btn = document.getElementById('populateBtn');
btn.onclick = () => {
const data = textArea.value.replace(/\t/g, '').split('\n');
chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
chrome.tabs.sendMessage(tab.id, {data}, () => {
if (chrome.runtime.lastError) {
chrome.tabs.executeScript({file: 'inject.js'}, () => {
chrome.tabs.sendMessage(tab.id, {data});
});
}
});
});
};
由于您没有在 sendMessage 中使用响应,因此首先不要发送它,即从 inject.js 中删除 sendResponse({result: "ok"}); return true;
。