[javascript] 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 호출의 성공 방법에서는 보내지 않습니다. 디버깅을 할 때 볼 수 있습니다. sendResponse함수 코드 내에서 포트가 널 입니다.



답변

에서 의 문서chrome.runtime.onMessage.addListener :

이 함수는 이벤트 리스너에서 true를 반환하여 응답을 비동기식으로 보내려는 것을 나타내지 않는 한 이벤트 리스너가 반환 될 때 유효하지 않습니다 (이는 sendResponse가 호출 될 때까지 메시지 채널을 다른 쪽 끝으로 열어 둡니다).

따라서 return true;호출 후에 getUrls응답 함수를 비동기 적으로 호출 할 것임을 나타 내기 위해 추가 하면됩니다.


답변

허용 된 답변은 정확합니다. 단순히 샘플 코드를 추가하고 싶었습니다. 문제는 API (내 관점에서)가 특정 메시지가 비동기로 처리되는지 여부를 개발자가 알도록 강제하기 때문에 잘 설계되지 않았다는 것입니다. 여러 가지 다른 메시지를 처리하는 경우 전달 된 sendResponse를 일부 함수의 깊이에 대해 알지 못하기 때문에 불가능한 작업이됩니다. 이걸 고려하세요:

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

깊은 handleMethod1통화가 비동기 인지 여부를 어떻게 알 수 있습니까? 수정 한 사람이 handleMethod1비동기식으로 무언가를 도입하여 발신자를 중단 시킬 것임을 어떻게 알 수 있습니까?

내 해결책은 이것입니다 :

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 에서이 작업을 수행 할 수 있습니다 .

코드는 다음과 같습니다.

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


답변