콘텐츠 스크립트와 확장 프로그램 사이에 메시지를 전달하려고합니다.
내용 스크립트에서 내가 가진 것입니다
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 }); });
}) );