chrome扩展-sendResponse不等待异步功能[重复]
Posted
技术标签:
【中文标题】chrome扩展-sendResponse不等待异步功能[重复]【英文标题】:chrome extension - sendResponse not waiting for async function [duplicate] 【发布时间】:2022-01-22 22:21:24 【问题描述】:我遇到了异步问题(我相信)。 contentscript.js 中的sendResponse()
不会等待getThumbnails()
返回。
我正在 popup.js 中发送 消息:
chrome.tabs.sendMessage(tabs[0].id, message: "get_thumbnails", tabUrl: tabs[0].url,
function (respThumbnails)
const thumbUrl = respThumbnails.payload;
console.log("payload", thumbUrl)
);
然后,在 contentscript.js 中,我收听这条消息:
chrome.runtime.onMessage.addListener(async function(request,sender,sendResponse)
if(request.message === "get_thumbnails")
const payload = await getThumbnails();
console.log("thumbPayload after function:", payload)
sendResponse(payload:payload);
);
async function getThumbnails()
let tUrl = null;
var potentialLocations = [
sel: "meta[property='og:image:secure_url']", attr: "content" ,
sel: "meta[property='og:image']", attr: "content" ,
];
for(s of potentialLocations)
if(tUrl) return
const el = document.querySelector(s.sel);
if(el)
tUrl = el.getAttribute(s.attr) || null;
return tUrl;
;
但问题也可能来自我的getThumnails()
函数,因为大多数时候,有效负载为空,而不是未定义。所以getThumbnails()
可能会在它完全执行之前返回。
如果是这种情况,我不知道为什么......
我也为getThubnails()
尝试了这段代码:
async function getThumbnails()
let x = await function()
let tUrl = null;
var potentialLocations = [
sel: "meta[property='og:image:secure_url']", attr: "content" ,
sel: "meta[property='og:image']", attr: "content" ,
];
for(s of potentialLocations)
if(tUrl) return
const el = document.querySelector(s.sel);
if(el)
tUrl = el.getAttribute(s.attr) || null;
return tUrl;
return x;
;
但这不起作用,它似乎破坏了我的代码......
【问题讨论】:
顺便说一句,document.querySelector 没有返回 Promise,所以等待它没有意义。 【参考方案1】:onMessage 的回调应该返回一个文字 true
值(documentation),以保持内部消息传递通道打开,以便 sendResponse 可以异步工作。
问题是,你的回调是用 async
关键字声明的,这意味着它返回一个 Promise
所以它不能返回一个文字 true
值。 Chrome 扩展 API 不支持回调返回值中的 Promise,所以它被忽略了。
使用标准函数回调和嵌套异步 IIFE:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) =>
if (request.message === "get_thumbnails")
(async () =>
const payload = await getThumbnails();
console.log("thumbPayload after function:", payload)
sendResponse(payload);
)();
return true; // keep the messaging channel open for sendResponse
);
【讨论】:
感谢您的回答。但是,我已尝试使用您的代码,但仍然无法正常工作。它返回空值。我的 getThumbnails() 函数一切正常吗?在我删除的 await document.querySelector 旁边:) 当您编辑内容脚本时,您需要在 chrome://extensions 页面上重新加载扩展,并重新加载运行该内容脚本的网页。至于那个功能,我根本看不到里面有任何需要async
和await
的东西。
是的,当然,我一直在重新加载扩展并刷新页面。您的代码实际上正在运行,但我仍然遇到问题的原因是因为我所在的页面有 6 或 7 帧。因为我的清单中有“all_frames”=true,所以会为每个帧发送一条新消息,并且它们都发送响应到我的 popup.js,但 popup.js 只收到 1 个响应,甚至发送了 6 个艰难的响应。 . 我不知道我是否清楚,但例如,我在我的内容脚本中执行 console.log("location:", document.location) ,它控制台记录 6 个不同的位置......我找不到解决方案..
iframe 问题是另一个问题。在我的脑海中,您可以简单地在弹出窗口中添加一个 runtime.onMessage 侦听器,并在您的内容脚本中使用 runtime.sendMessage 而不是 sendResponse。或者,您可以切换到 tabs.executeScript,而不是使用消息传递声明的内容脚本,这样您就可以将所有帧的输出收集到一个数组中。
我在弹出窗口和浏览器操作菜单中有相同的代码,在持久背景页面中有一个 onMessage 处理程序。奇怪的是,在使处理程序异步后,弹出窗口工作得很好。只是在回去测试菜单后,我才意识到有些东西坏了。如果弹出窗口也没有打开,则菜单工作正常。但如果是这样,从菜单发出的对后台的等待异步调用永远不会收到响应。打开两个页面(和两个端口)似乎打破了它。将等待从处理程序中移出修复了问题。以上是关于chrome扩展-sendResponse不等待异步功能[重复]的主要内容,如果未能解决你的问题,请参考以下文章
BluetoothGattServer.sendResponse 中的数据长度不能超过 20 字节。 (低功耗蓝牙)
致命异常:NSInternalInconsistencyException 此请求已被绝育 - 您不能调用 -sendResponse: 两次,也不能在编码后调用