2010-11-15 10 views
1

Je construis une extension dans Google Chrome qui émet des requêtes sur des sites Web.Passage de message d'extension Chrome, lorsque l'appel xhr échoue dans jQuery

Les requêtes sont émises par la "page d'arrière-plan" sur demande du "script de contenu"; lorsque la page d'arrière-plan reçoit une requête pour émettre une requête, elle envoie la requête, analyse la réponse et renvoie la réponse au script de contenu, en utilisant sendResponse().

Tout fonctionne correctement lors de l'utilisation de XMLHttpRequest(); mais mon problème est que si je veux lancer des requêtes en utilisant jQuery .get() ou .load(), alors quand les requêtes échouent, elles échouent silencieusement et la réponse n'est jamais envoyée au script de contenu.

Si j'enregistre un gestionnaire d'événements avec .ajaxError() l'erreur est attrapée, mais de ce gestionnaire d'événements, je ne peut apparemment pas appeler sendResponse() parce que je reçois l'erreur Chrome suivante:

« Toute tentative d'utiliser un déconnecté objet port "

La recherche de cette erreur ne récupère que le code source de Chrome où ce texte est trouvé, donc ce n'est pas très utile. En bref, ma question est la suivante: est-il possible d'utiliser jQuery.get() dans un script d'arrière-plan d'une extension Chrome, tout en pouvant envoyer une réponse au script de contenu lorsque la requête échoue? (et si oui, comment)

+0

Pouvez-vous s'il vous plaît poster un code? – serg

Répondre

1

Il est difficile de répondre directement, sans un exemple de code (comment avez-vous de passage sendResponse au gestionnaire d'erreur ?), mais je pense qu'il existe des alternatives à la construction du XHR.

  • Répondre de manière asynchrone: vous pouvez envoyer une réponse vide immédiatement au script contenu, puis plus tard lancer une nouvelle connexion au script de contenu pour envoyer la réponse. Le script de contenu devra ajouter un écouteur pour les messages. Évidemment, si vous faites plusieurs de ces demandes, vous voudrez que des jetons soient échangés afin que vous puissiez faire correspondre les réponses à leurs demandes d'origine.
  • Utilisez $.ajax(): cela vous permet de spécifier à la fois un succès et un rappel d'erreur en ligne; Si vous réussissez sendResponse à partir du rappel de succès, vous devriez également être en mesure de partir du rappel d'erreur.
  • Créer un port de longue durée: long-living connections vous permet de publier un message dans le script de contenu à tout moment.

Je voudrais aussi penser que l'on pourrait appeler sendResponse d'une fonction à part entière si vous avez enregistré la fonction sendResponse afin qu'il soit accessible au gestionnaire d'erreur, mais peut-être vous ai prouvé que le faux déjà (serait J'adore avoir vu ton code). La documentation donne l'impression que la demande est ouverte jusqu'à ce que vous y répondiez.

+0

Vous avez raison, en utilisant $ .ajax() permet de spécifier une fonction de rappel d'erreur; mais c'est probablement un peu plus complexe que ma simple fonction XHR. D'ailleurs, la seule raison pour laquelle j'inclus jQuery dans le script de fond était pour cela; Avec ma propre fonction XHR, je n'ai même plus besoin de jQuery dans la page d'arrière-plan. – Bambax

0

Après avoir regardé le code pour voir si je pouvais en extraire une partie pour construire un exemple de travail (en réponse au commentaire serg), je ne pense pas que ce que je veux faire soit possible avec jQuery. En jQuery, lorsqu'un appel ajax échoue, un événement d'erreur est appelé (pour qu'il soit intercepté par le gestionnaire d'événements .ajaxError()), puis la fonction se termine/retourne. Lorsque le gestionnaire .ajaxError() s'exécute, la fonction est donc morte. (Cela, je crois, est le point entier du système d'événement asynchrone dans JS).

Maintenant, je ne fais que deviner ici, mais je pense que dans Chrome, le canal de communication entre le script de contenu et le script d'arrière-plan est fermé lorsque la fonction d'écoute a été exécutée; on ne peut pas envoyer une réponse du script d'arrière-plan au script de contenu après la fin de la fonction d'écouteur, ce que j'essayais de faire en manipulant l'erreur ajax dans un gestionnaire d'événement. Donc, ce que j'ai fini par faire était de ré-implémenter une fonction ajax qui renvoie réellement un objet complet: si l'appel échoue, il retourne le fait qu'il y a eu une erreur, avec le code d'erreur, de sorte que la fonction caller (en réalité un callback) peut le gérer et renvoyer une réponse au script de contenu.

Il est seulement quelques lignes, et (je pense) tout à fait générique, il est donc ici:

function xhr(url, callback) { 
    var req = new XMLHttpRequest(); 
    req.open("GET", url, true); 
    req.onreadystatechange = function() { 
     if (req.readyState == 4) { 
      var resp = { 
       "url": url, 
       "status": req.status 
       }; 
      if (req.status == 200) { 
       resp.html = req.responseText; 
       resp.outcome = "ok"; 
       } 
      else { 
       resp.outcome = "error"; 
       } 
      callback(resp); 
      } 
     } 
    req.send(null); 
    }