2

メタデータを抽出するChrome拡張機能に取り組んでいます。メタデータを解析するコードは、コンテンツスクリプトに含まれています。background.jsとcontent.jsは、sendMessageのリクエストとレスポンスを介して通信します。sendMessageリクエストの非同期性に関する問題が発生しており、それを修正する方法がわかりません(この問題に関する一連の議論を読んだ後でも)。任意のアドバイスや指示をいただければ幸いです。これらをコールバックに変換する方法がわからないのではないかと思います。

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

content.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

応答があるときに呼び出す関数 (最大 1 回)。引数は、任意の JSON 化可能なオブジェクトである必要があります。同じドキュメントに複数の onMessage リスナーがある場合、応答を送信できるのは 1 つだけです。この関数は、イベント リスナーから返されたときに無効になります。ただし、イベント リスナーから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. listenerinonMessageを設定して非同期応答を待機し、それを使用して送信しasyncても役に立ちませんawaitsendResponse

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 に答える