Chrome Extension Message passing: response not sent
我试图在内容脚本和扩展名之间传递消息
这是我在content-script中的内容
1 2 3 | chrome.runtime.sendMessage({type:"getUrls"}, function(response) { console.log(response) }); |
在我的后台脚本中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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}) } }); } |
现在,如果我在
从
This function becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called).
因此,您只需在调用
接受的答案是正确的,我只想添加简化此示例的示例代码。
问题是API(在我看来)设计得不好,因为它迫使我们的开发人员知道特定的消息是否会被异步处理。如果您处理许多不同的消息,这将成为一项不可能完成的任务,因为您永远不知道某些函数是否内部传递的sendResponse将被称为async。
考虑一下:
1 2 3 4 | chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) { if (request.method =="method1") { handleMethod1(sendResponse); } |
如何深入
我的解决方案是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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; } }); |
无论您选择如何处理消息,这都会自动处理返回值。请注意,这假设您永远不会忘记调用响应函数。另请注意,铬可以为我们自动化,我不明白为什么他们没有。
您可以使用我的库https://github.com/lawlietmester/webextension,使用Firefox方式在Chrome和FF中使用它,而无需回调。
您的代码将如下所示:
1 2 3 4 5 6 7 8 | 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 }); }); }) ); |