Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/444.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Chrome扩展消息传递:未发送响应_Javascript_Google Chrome_Google Chrome Extension_Google Chrome App - Fatal编程技术网

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

Javascript Chrome扩展消息传递:未发送响应,javascript,google-chrome,google-chrome-extension,google-chrome-app,Javascript,Google Chrome,Google Chrome Extension,Google Chrome App,我正在尝试在内容脚本和扩展之间传递消息 以下是我在内容脚本中的内容 chrome.runtime.sendMessage({type: "getUrls"}, function(response) { console.log(response) }); 在我的背景剧本中 chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { if (request.type == "getU

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

以下是我在内容脚本中的内容

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调用的成功方法中,它不会发送响应,当我进入调试时,我可以看到sendResponse函数的代码中的端口为null。

From:

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


所以您只需要添加returntrue;在调用getURL以指示您将异步调用响应函数之后。

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

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

});
这将自动处理返回值,而不管您选择如何处理消息。注意,这假设您永远不会忘记调用响应函数。还要注意的是,Chrome可以为我们实现自动化,我不明白为什么他们没有做到。

您可以使用我的库在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 }); });
}) );

这是正确的,我在我的答案+1中为此添加了一种自动化方法。在花了2天的时间调试这个问题后,它救了我。我不敢相信,在《信息传递指南》中根本没有提到这一点:我以前显然有过这个问题;回来后才意识到我已经把这个投了更高的票。这需要在页面上的某个地方用粗体和标记表示。@funforms仅供参考,此行为现在已在文档中记录。区别在于:。我发誓这是我使用过的最不直观的API。一个问题是,有时您不想调用响应函数,在这种情况下,您应该返回false。如果你不这样做,你就是在阻止Chrome释放与消息相关的资源。是的,这就是为什么我说不要忘记调用回调。可以通过约定处理程序handleMethod1 etc返回false来处理这种特殊情况,以指示无响应情况,尽管Id总是做出响应,甚至是空响应。这样,可维护性问题只局限于那些特殊的不可恢复情况。不要重新发明轮子。不推荐使用的chrome.extension.onRequest/chrome.exension.sendRequest方法的行为与您描述的完全相同。这些方法被弃用,因为许多扩展开发人员没有关闭消息端口。当前需要返回true的API是一个更好的设计,因为硬失败比无声泄漏要好。@RobW但是问题是什么呢?我的回答可以防止开发人员忘记返回true。@ZigMandel如果要发送响应,只需使用return true;。当异步调用仍在正确处理时,如果调用是同步的,则不会阻止清除端口。此答案中的代码引入了不必要的复杂性,但没有明显的好处。存储对sendResponse参数的引用至关重要。没有它,响应对象将超出范围,无法调用。谢谢你的代码,它提示我解决我的问题!也许另一种解决方案是用异步方法的Promise和callwait将所有内容包装在异步函数中?