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

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

这是我在内容脚本中的内容

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调用的成功方法没有发送,当我进入debugging时,我可以看到该端口在sendResponse函数的代码内是空的。

chrome.runtime.onMessage.addListener的文档 :

当事件监听器返回时,这个函数将变为无效,除非你从事件​​监听器返回true来指示你希望asynchronous发送一个响应(这将使消息通道保持打开状态直到sendResponse被调用)。

所以你只需要添加return true; 在调用getUrls ,指示你将asynchronous调用响应函数。

接受的答案是正确的,我只是想添加示例代码,简化了这一点。 问题是API(在我看来)devise得不好,因为它迫使我们的开发人员知道一个特定的消息是否会被asynchronous处理。 如果你处理许多不同的消息,这成为一个不可能的任务,因为你永远不知道是否深入一些函数传入的sendResponse将被称为asynchronous或不。 考虑一下:

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

我怎么知道,如果深入handleMethod1调用将是asynchronous或不? 一个修改handleMethod1handleMethod1知道它会通过引入asynchronous来打断调用者呢?

我的解决办法是:

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

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

您可以使用我的图书馆https://github.com/lawlietmester/webextension在Chrome和Firefox中使用Firefox方式进行此项工作,无需callback。;

您的代码将如下所示:

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