2

我正在开发一个提取元数据的 chrome 扩展。解析元数据的代码包含在内容脚本中。background.js 和 content.js 通过 sendMessage 请求和响应进行通信。我遇到了 sendMessage 请求的异步性质的问题,我不确定如何解决它(即使在阅读了关于该问题的一连串讨论之后)。任何建议或方向将不胜感激。我怀疑我不知道如何将这些转换为回调。

背景.js:

function onContextClick(info, tab) {    
  if( info["selectionText"] ){  
    var x = getMeta(tab);   
    //do stuff with x       
  }
}

function getMeta (tab) {
chrome.tabs.sendMessage(tab.id, {fetchTag: "meta,name,author,content"}, function(response) {
    //alert(response.data);
    //one thing I tired was to put my "do stuff" embedded here, but that didn't work either         
    return response.data; 
    });
}

var menu_id = chrome.contextMenus.create({"title": "Get Meta", "contexts":["selection"], "onclick": onContextClick});

内容.js:

function fetchTag(string) {
    var param = string.split(",");
    return $(param[0] + "["+param[1]+ "=\"" + param[2] + "\"]").attr(param[3]); 
    }

chrome.extension.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.fetchTag.length > 0)        
    sendResponse({data: fetchTag(request.fetchTag)});
  });
4

3 回答 3

8

来自:https ://developer.chrome.com/extensions/runtime#event-onMessage

有响应时调用的函数(最多一次)。参数应该是任何 JSON-ifiable 对象。如果您在同一个文档中有多个 onMessage 侦听器,那么只有一个可以发送响应。当事件侦听器返回时,此函数无效,除非您从事件侦听器返回 true以指示您希望异步发送响应(这将保持消息通道对另一端开放,直到调用 sendResponse )。

chrome.extension.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.fetchTag.length > 0)        
    sendResponse({data: fetchTag(request.fetchTag)});
    return true;
});

然后它将与异步代码一起使用。

于 2018-11-16T16:55:00.380 回答
1

就我而言,

  1. 按照文档的建议简单地添加return true并没有帮助
  2. 设置listenerin onMessagetoasync和 useawait以等待异步响应并使用它发送它sendResponse没有帮助

没有帮助我的意思是 Chrome 控制台中发生以下错误:

Unchecked runtime.lastError: The message port closed before a response was received.

经过一些实验,我发现以下方法可以很好地异步发送响应。

// content.js
chrome.runtime.sendMessage({ type: "GET_FOO" }, function (response) {
  console.log(response.foo);
});
// background.js

// replace with a real call that
// needs to run asynchronously
async function getFoo() {
  return "bar"
}

async function sendFoo(sendResponse) {
  const foo = await getFoo()
  sendResponse({ foo })
}

chrome.runtime.onMessage.addListener(
  function (request, sender, sendResponse) {
    if (request.type === "GET_FOO") {
      sendFoo(sendResponse)
      return true
    }
  }
);

在 Chrome 92.0.4515.159(官方版本)(x86_64)上测试。

于 2021-08-25T20:09:57.633 回答
-1

您可以使用闭包。这样。

function onContextClick(info, tab) {    
  if( info["selectionText"] ){  
    getMeta(tab, function(x){
      console.log(x);
      //do stuff with x
    });
  }
}

function getMeta (tab, callback) {
chrome.tabs.sendMessage(tab.id, {fetchTag: "meta,name,author,content"}, function(response) {
    //alert(response.data);
    //one thing I tired was to put my "do stuff" embedded here, but that didn't work either
    callback(response.data);
    });
}
于 2012-12-30T21:14:57.637 回答