Tho*_*dax 1 javascript firefox-addon firefox-addon-webextensions
我制作了一个与可执行文件交互的 Firefox WebExtension(使用runtime.connectNative)。
这是扩展的清单:
// manifest.json file
{
"name": "My Extension",
"short_name": "myext",
"version": "2.7",
"manifest_version": 2,
"background": {
"scripts": ["background-script.js"],
"persistent": true
},
"externally_connectable": {
"ids": ["*"],
"http://localhost/*"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content-script.js"]
}
],
"applications": {
"gecko": {
"id": "myext@myext.mysite.com",
"strict_min_version": "50.0.0"
}
},
"icons": {
"16": "icon-16.png",
"32": "icon-32.png",
"128": "icon-128.png"
},
"permissions": [
"nativeMessaging",
"webRequest"
]
}
Run Code Online (Sandbox Code Playgroud)
这是内容脚本:
// content-script.js
window.addEventListener("message", function(event) {
if (event.source == window &&
event.data.direction &&
event.data.direction == "from-page-script") {
alert("Content script received message: \"" + JSON.stringify(event.data.message) + "\"");
var sending = browser.runtime.sendMessage(event.data.message);
sending.then(handleResponse, handleError);
}
});
function handleResponse(message)
{
console.log("content-script : handleResponse : message = " + JSON.stringify(message));
window.wrappedJSObject.foo.p = "OK : " + JSON.stringify(message);
}
function handleError(error) {
console.log("Message from the background script : " + error.message);
window.wrappedJSObject.foo.p = "error";
}
Run Code Online (Sandbox Code Playgroud)
这是我的背景脚本:
// background-script.js
var port;
browser.runtime.onMessage.addListener(function(request, sender, sendResponse)
{
port = browser.runtime.connectNative("ping_pong");
var result = port.postMessage(request);
port.onMessage.addListener(function(response)
{
console.log("Received: " + JSON.stringify(response));
sendResponse(response);
});
});
Run Code Online (Sandbox Code Playgroud)
我对后台脚本中的以下行有疑问:
sendResponse(response);
Run Code Online (Sandbox Code Playgroud)
handleResponse()内容脚本的方法sendResponse()在后台脚本之前调用。
因此,当可执行文件需要更长的时间来执行操作时,可执行文件的结果不会发送到内容脚本,内容脚本会收到未定义的结果。
是否有另一种方法将可执行文件的结果从后台脚本发送到内容脚本?或者以另一种方式使用回调?
Promise的使用在这里引起了一些混乱。您handleResponse()的 Promise 被调用时没有任何参数,因为您退出了后台脚本的runtime.onMessage侦听器而没有调用sendResponse(). 如果sendResponse()已被调用,则参数将是消息1。因此,您需要调整您的.then()参数以区分不接收参数(sendResponse()未调用)和包含响应消息的参数(sendResponse()调用)。如果我没记错的话,如果您使用的是chrome.runtime.sendMessage(),responseCallback除非调用,否则不会调用您的函数sendResponse()。
如果发送方发送了响应,这将通过作为 JSON 对象的响应来实现。否则它将在没有参数的情况下实现。如果在连接到扩展时发生错误,promise 将被拒绝并显示错误消息。
sendResponse()异步调用,您需要return true;从您的runtime.onMessage侦听器您sendResponse()从异步回调中调用。因此,您runtime.onMessage在sendResponse()被调用之前退出侦听器。如果您打算这样做,并且仍想调用sendResponse(),则需要true从runtime.onMessage侦听器返回。
来自MDNruntime.onMessage关于sendResponse():
此函数返回一个
boolean.true如果您希望sendResponse在事件侦听器返回后调用,它应该从事件侦听器返回。
所以你的代码可能是:
browser.runtime.onMessage.addListener(function(request, sender, sendResponse)
{
port = browser.runtime.connectNative("ping_pong");
var result = port.postMessage(request);
port.onMessage.addListener(function portOnMessageListener(response)
{
//sendResponse is only valid once. So, if this is how you want to use it, you need
// to remove the listener, or in some other way not call sendResponse twice.
port.onMessage.removeListener(portOnMessageListener);
console.log("Received: " + JSON.stringify(response));
sendResponse(response);
});
return true;
});
Run Code Online (Sandbox Code Playgroud)
sendResponse() 仅有效一次该sendResponse()函数仅对一条消息有效(即,每条消息只能发送一个响应)。如果您希望向内容脚本发送多条消息,则需要以不同的方式进行设置。
| 归档时间: |
|
| 查看次数: |
2586 次 |
| 最近记录: |