javascript Chrome扩展消息传递:未发送响应

wbrvyc0a  于 2023-03-28  发布在  Java
关注(0)|答案(3)|浏览(180)

我正在尝试在内容脚本和扩展之间传递消息
这是我在内容脚本

chrome.runtime.sendMessage({type: "getUrls"}, function(response) {
  console.log(response)
});

在我的背景脚本中

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.type == "getUrls"){
      getUrls(request, sender, sendResponse)
    }
});

function getUrls(request, sender, sendResponse){
  var resp = sendResponse;
  $.ajax({
    url: "http://localhost:3000/urls",
    method: 'GET',
    success: function(d){
      resp({urls: d})
    }
  });

}

现在,如果我在getUrls函数中 AJAX 调用之前发送响应,则响应发送成功,但在ajax调用的success方法中,当我发送响应时,它不会发送它,当我进入调试时,我可以看到sendResponse函数代码中的端口为null。

lstz6jyr

lstz6jyr1#

来自chrome.runtime.onMessage.addListener的文档:
如果你想异步使用sendResponse(),添加return true;到onMessage事件处理程序。
因此,您只需要在调用getUrls之后添加return true;,以表明您将异步调用响应函数。
请注意,其他文档(例如onMessage文档)中没有提到这一点,因此开发人员可能会忽略这一点。

9fkzdhlc

9fkzdhlc2#

公认的答案是正确的我只是想添加一些示例代码来简化这一点。(在我看来)设计得不好,因为它迫使我们开发人员知道特定的消息是否会被异步处理。如果你处理许多不同的消息,这就变成了一个不可能的任务,因为你永远不知道在某些函数的深处,传入的sendResponse是否会被异步调用。想想这个:

chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
if (request.method == "method1") {
    handleMethod1(sendResponse);
}

我怎么知道handleMethod1的调用是否是异步的?修改handleMethod1的人怎么知道它会通过引入异步的东西来破坏调用者?
我的解决方案是:

chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {

    var responseStatus = { bCalled: false };

    function sendResponse(obj) {  //dummy wrapper to deal with exceptions and detect async
        try {
            sendResponseParam(obj);
        } catch (e) {
            //error handling
        }
        responseStatus.bCalled= true;
    }

    if (request.method == "method1") {
        handleMethod1(sendResponse);
    }
    else if (request.method == "method2") {
        handleMethod2(sendResponse);
    }
    ...

    if (!responseStatus.bCalled) { //if its set, the call wasn't async, else it is.
        return true;
    }

});

这会自动处理返回值,不管你选择如何处理消息。注意,这假设你永远不会忘记调用响应函数。还要注意,chromium可以为我们自动化这一点,我不明白为什么他们没有。

3df52oht

3df52oht3#

你可以使用我的库https://github.com/lawlietmester/webextension在Chrome和FF中使用Firefox的方式实现这一点,而无需回调。
你的代码看起来像这样:

Browser.runtime.onMessage.addListener( request => new Promise( resolve => {
    if( !request || typeof request !== 'object' || request.type !== "getUrls" ) return;

    $.ajax({
        'url': "http://localhost:3000/urls",
        'method': 'GET'
    }).then( urls => { resolve({ urls }); });
}) );

相关问题