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

Abi*_*bid 146 javascript google-chrome google-chrome-extension google-chrome-app

我试图在内容脚本和扩展名之间传递消息

这是我在content-script中的内容

chrome.runtime.sendMessage({type: "getUrls"}, function(response) {
  console.log(response)
});
Run Code Online (Sandbox Code Playgroud)

在我的后台脚本中

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})
    }
  });

}
Run Code Online (Sandbox Code Playgroud)

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

rsa*_*hez 335

以下文档chrome.runtime.onMessage.addListener:

当事件侦听器返回时,此函数变为无效,除非您从事件侦听器返回true以指示您希望异步发送响应(这将使消息通道保持打开到另一端,直到调用sendResponse).

因此,您只需return true;在调用后添加,getUrls以指示您将异步调用响应函数.

  • +1为此.在浪费了2天试图调试此问题后,它已经救了我.我无法相信在消息传递指南中根本没有提到这一点:https://developer.chrome.com/extensions/messaging (60认同)
  • 我发誓这是我用过的最不直观的API. (7认同)
  • 我以前显然有这个问题; 回过头来意识到我已经投了这个.这需要在页面的某处用大的`<blink>`和`<marquee>`标签加粗. (6认同)
  • 不幸的是,这似乎不适用于 async/await... (3认同)
  • @funforums仅供参考,此行为现已记录在[messaging](https://developer.chrome.com/extensions/messaging)文档中(区别在于:https://codereview.chromium.org/1874133002/patch/九万〇二分之八万〇一). (2认同)

Zig*_*del 8

接受的答案是正确的,我只想添加简化此示例的示例代码.问题是API(在我看来)设计得不好,因为它迫使我们的开发人员知道特定的消息是否会被异步处理.如果您处理许多不同的消息,这将成为一项不可能完成的任务,因为您永远不知道某些函数是否内部传递的sendResponse将被称为async.考虑一下:

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

我怎么知道内部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;
}

});
Run Code Online (Sandbox Code Playgroud)

无论您选择如何处理消息,这都会自动处理返回值.请注意,这假设您永远不会忘记调用响应函数.另请注意,铬可以为我们自动化,我不明白为什么他们没有.

  • 不要重新发明轮子.不推荐使用的`chrome.extension.onRequest` /`chrome.exension.sendRequest`方法的行为与您描述的完全相同.不推荐使用这些方法,因为事实证明许多扩展开发人员没有关闭消息端口.当前的API(要求'返回true`)是一个更好的设计,因为失败比没有安静地泄漏更好. (8认同)