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或不? 一个修改handleMethod1
人handleMethod1
知道它会通过引入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 }); }); }) );