Javascript browser.runtime.sendMessage()在异步调用sendResponse()之前履行的承诺

Javascript browser.runtime.sendMessage()在异步调用sendResponse()之前履行的承诺,javascript,firefox-addon,firefox-addon-webextensions,Javascript,Firefox Addon,Firefox Addon Webextensions,我制作了一个FirefoxWebExtension,它可以与可执行文件交互(使用) 以下是扩展的清单: // manifest.json file { "name": "My Extension", "short_name": "myext", "version": "2.7", "manifest_version": 2, "background": { "scripts": ["background-script.js"], "persistent":

我制作了一个FirefoxWebExtension,它可以与可执行文件交互(使用)

以下是扩展的清单:

// 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"
    ]
}
这是我的背景脚本:

// 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);
    });
});
sendResponse(response);
我对背景脚本中的以下行有问题:

// 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);
    });
});
sendResponse(response);
在后台脚本的
sendResponse()
之前调用内容脚本的方法
handleResponse()

因此,当可执行文件执行操作所需时间较长时,可执行文件的结果不会发送到内容脚本,而内容脚本会收到未定义的结果

是否有其他方法将可执行文件的结果从后台脚本发送到内容脚本?或者以另一种方式使用回调?

的使用在这里造成了一些混乱。调用您的
HandlerResponse()
时,承诺已实现,但没有参数,因为您未调用
sendResponse()
而退出了后台脚本的
运行时.onMessage
侦听器。如果调用了
sendResponse()
,则参数将是message1。因此,您需要调整
.then()
以区分未接收参数(
sendResponse()
未调用)和包含响应消息的参数(
sendResponse()
调用)。如果我没记错的话,如果您使用的是
chrome.runtime.sendMessage()
,则除非调用
sendResponse()
,否则不会调用您的
responseCallback
函数

:

如果发送方发送了响应,则响应将作为JSON对象来实现。否则,它将在没有参数的情况下实现。如果在连接到扩展时发生错误,承诺将被拒绝并显示错误消息

要异步调用
sendResponse()
,需要
返回true
运行时.onMessage
侦听器 您正在从异步回调中调用
sendResponse()
。因此,在调用
sendResponse()
之前,您将退出
runtime.onMessage
侦听器。如果要执行此操作,但仍要调用
sendResponse()
,则需要从
运行时.onMessage
侦听器返回
true

关于
sendResponse()

此函数返回一个
布尔值。如果您希望在事件侦听器返回后调用
sendResponse
,它应该从事件侦听器返回
true

因此,您的代码可以是:

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;
});
sendResponse()
仅有效一次
sendResponse()
函数仅对一条消息有效(即,每发送一条消息,您只能发送一条响应)。如果希望向内容脚本发送多条消息,则需要以不同的方式进行设置


  • 该消息是一个“JSON对象”。他们可能的意思是,它是从JSON转换而来的,JSON在消息传输过程中被用来表示它
  • 在这里使用的是引起一些混乱。调用您的
    HandlerResponse()
    时,承诺已实现,但没有参数,因为您未调用
    sendResponse()
    而退出了后台脚本的
    运行时.onMessage
    侦听器。如果调用了
    sendResponse()
    ,则参数将是message1。因此,您需要调整
    .then()
    以区分未接收参数(
    sendResponse()
    未调用)和包含响应消息的参数(
    sendResponse()
    调用)。如果我没记错的话,如果您使用的是
    chrome.runtime.sendMessage()
    ,则除非调用
    sendResponse()
    ,否则不会调用您的
    responseCallback
    函数

    :

    如果发送方发送了响应,则响应将作为JSON对象来实现。否则,它将在没有参数的情况下实现。如果在连接到扩展时发生错误,承诺将被拒绝并显示错误消息

    要异步调用
    sendResponse()
    ,需要
    返回true
    运行时.onMessage
    侦听器 您正在从异步回调中调用
    sendResponse()
    。因此,在调用
    sendResponse()
    之前,您将退出
    runtime.onMessage
    侦听器。如果要执行此操作,但仍要调用
    sendResponse()
    ,则需要从
    运行时.onMessage
    侦听器返回
    true

    关于
    sendResponse()

    此函数返回一个
    布尔值。如果您希望在事件侦听器返回后调用
    sendResponse
    ,它应该从事件侦听器返回
    true

    因此,您的代码可以是:

    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;
    });
    
    sendResponse()
    仅有效一次
    sendResponse()
    函数仅对一条消息有效(即,每发送一条消息,您只能发送一条响应)。如果希望向内容脚本发送多条消息,则需要以不同的方式进行设置


  • 该消息是一个“JSON对象”。他们可能的意思是,它是从JSON转换而来的,JSON在消息传输过程中被用来表示它

  • 非常感谢您的快速和详尽answer@Thordax,我很高兴能帮上忙。如果要从
    端口
    获取多条消息,可以使用多种方法。但是,看起来您并没有期望端口上出现多条消息。如果是我,只是为了测试,在删除主侦听器之后,我可能会添加另一个侦听器,在出现其他问题时记录错误或警告。在发展中,这将