J'essaie de transmettre des messages entre le script de contenu et l'extension
Voici ce que j'ai dans content-script
chrome.runtime.sendMessage({type: "getUrls"}, function(response) {
console.log(response)
});
Et dans le script d'arrière-plan j'ai
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})
}
});
}
Maintenant, si j’envoie la réponse avant l’appel ajax dans la fonction getUrls
, la réponse est envoyée avec succès, mais dans la méthode de succès de l’appel ajax lorsque j’envoie la réponse, elle ne l’envoie pas, quand je vais dans le débogage, je peux voir que le port est nul dans le code de la fonction sendResponse
.
De la documentation pour chrome.runtime.onMessage.addListener
:
Cette fonction devient invalide lorsque l'écouteur d'événements est renvoyé, à moins que vous ne renvoyiez la valeur true à partir de l'écouteur d'événements pour indiquer que vous souhaitez envoyer une réponse asynchrone (le canal du message restera ouvert jusqu'à l'autre extrémité jusqu'à l'appel de sendResponse).
Il suffit donc d’ajouter return true;
après l'appel à getUrls
pour indiquer que vous appelez la fonction de réponse de manière asynchrone.
La réponse acceptée est correcte, je voulais juste ajouter un exemple de code qui simplifie cela. Le problème est que l'API (à mon avis) n'est pas bien conçue car elle oblige les développeurs à savoir si un message particulier sera traité de manière asynchrone ou non. Si vous gérez de nombreux messages différents, cela devient une tâche impossible car vous ne saurez jamais si au fond de quelque fonction un sendResponse transmis sera appelé asynchrone ou non. Considère ceci:
chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
if (request.method == "method1") {
handleMethod1(sendResponse);
}
Comment puis-je savoir si au fond handleMethod1
L'appel sera asynchrone ou non? Comment quelqu'un qui modifie handleMethod1
Peut-il savoir que l'appelant sera cassé en introduisant quelque chose d'async?
Ma solution est la suivante:
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;
}
});
Cela gère automatiquement la valeur de retour, quelle que soit la manière dont vous choisissez de gérer le message. Notez que cela suppose que vous n'oubliiez jamais d'appeler la fonction de réponse. Notez également que le chrome aurait pu automatiser cela pour nous, je ne vois pas pourquoi ils ne l'ont pas fait.
Vous pouvez utiliser ma bibliothèque https://github.com/lawlietmester/webextension pour que cela fonctionne à la fois Chrome et FF avec Firefox sans rappel.
Votre code ressemblera à:
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 }); });
}) );