2012-08-12 17 views
5

Estoy desarrollando un complemento por primera vez. Coloca un pequeño widget en la barra de estado que muestra la cantidad de elementos no leídos de Google Reader. Para adaptarse a esto, el proceso complementario consulta la API de Google Reader cada minuto y pasa la respuesta al widget. Cuando corro cfx test consigo este error:Error: la página se ha destruido y ya no se puede usar

Error: The page has been destroyed and can no longer be used.

que se aseguró de coger caso del widget detach y detener el temporizador de actualización en respuesta, pero todavía estoy viendo el error. ¿Qué estoy haciendo mal? Aquí está el código correspondiente:

// main.js - Main entry point 
const tabs = require('tabs'); 
const widgets = require('widget'); 
const data = require('self').data; 
const timers = require("timers"); 
const Request = require("request").Request; 

function refreshUnreadCount() { 
    // Put in Google Reader API request 
    Request({ 
     url: "https://www.google.com/reader/api/0/unread-count?output=json", 
     onComplete: function(response) { 
      // Ignore response if we encountered a 404 (e.g. user isn't logged in) 
      // or a different HTTP error. 
      // TODO: Can I make this work when third-party cookies are disabled? 
      if (response.status == 200) { 
       monitorWidget.postMessage(response.json); 
      } else { 
       monitorWidget.postMessage(null); 
      } 
     } 
    }).get(); 
} 

var monitorWidget = widgets.Widget({ 
    // Mandatory widget ID string 
    id: "greader-monitor", 

    // A required string description of the widget used for 
    // accessibility, title bars, and error reporting. 
    label: "GReader Monitor", 
    contentURL: data.url("widget.html"), 
    contentScriptFile: [data.url("jquery-1.7.2.min.js"), data.url("widget.js")], 

    onClick: function() { 
     // Open Google Reader when the widget is clicked. 
     tabs.open("https://www.google.com/reader/view/"); 
    }, 

    onAttach: function(worker) { 
     // If the widget's inner width changes, reflect that in the GUI 
     worker.port.on("widthReported", function(newWidth) { 
      worker.width = newWidth; 
     }); 

     var refreshTimer = timers.setInterval(refreshUnreadCount, 60000); 

     // If the monitor widget is destroyed, make sure the timer gets cancelled. 
     worker.on("detach", function() { 
      timers.clearInterval(refreshTimer); 
     }); 

     refreshUnreadCount(); 
    } 
}); 

// widget.js - Status bar widget script 

// Every so often, we'll receive the updated item feed. It's our job 
// to parse it. 
self.on("message", function(json) { 
    if (json == null) { 
     $("span#counter").attr("class", ""); 
     $("span#counter").text("N/A"); 
    } else { 
     var newTotal = 0; 
     for (var item in json.unreadcounts) { 
      newTotal += json.unreadcounts[item].count; 
     } 

     // Since the cumulative reading list count is a separate part of the 
     // unread count info, we have to divide the total by 2. 
     newTotal /= 2; 
     $("span#counter").text(newTotal); 

     // Update style 
     if (newTotal > 0) 
      $("span#counter").attr("class", "newitems"); 
     else 
      $("span#counter").attr("class", ""); 
    } 

    // Reports the current width of the widget 
    self.port.emit("widthReported", $("div#widget").width()); 
}); 

Editar: He subido el proyecto en su totalidad a this GitHub repository.

+0

Este error viene a su postMessage. ¿Has probado con 'monitorWidget.port.emit (" widthReported ", response.json);'? –

+0

@Charles: Pude solucionar el problema debido a su comentario. ¿Podría publicar esto como respuesta para que sea elegible para la recompensa? – Pieter

+0

Sí, lo hago ahora, pero no puedo dar más explicaciones:/ –

Respuesta

0

Creo que si utiliza el método monitorWidget.port.emit("widthReported", response.json); puede desencadenar el evento. Es la segunda forma de comunicarse con el script de contenido y el script complementario.

+0

¡Gracias de nuevo, la recompensa es tuya! – Pieter

+0

Para referencia futura, agregaré un enlace a [Problemas de sincronización usando postMessage] (https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/guides/content-scripts /using-postmessage.html) aquí. – Pieter

0

Supongo que este mensaje aparece cuando llamas al monitorWidget.postMessage() en refreshUnreadCount(). La causa obvia de esto sería: mientras se asegura de llamar al refreshUnreadCount() solo cuando el trabajador todavía está activo, esta función hará una solicitud asíncrona que puede llevar un tiempo. Entonces, cuando se completa esta solicitud, el trabajador ya puede haber sido destruido.

Una solución sería pasar el trabajador como parámetro al refreshUnreadCount(). A continuación, podría agregar su propio oyente detach (eliminarlo cuando se realiza la solicitud) e ignorar la respuesta si el trabajador se separó mientras se realizaba la solicitud.

function refreshUnreadCount(worker) { 
    var detached = false; 
    function onDetach() 
    { 
     detached = true; 
    } 
    worker.on("detach", onDetach); 

    Request({ 
     ... 
     onComplete: function(response) { 
      worker.removeListener("detach", onDetach); 
      if (detached) 
       return; // Nothing to update with out data 

      ... 
     } 
    }).get(); 
} 

Por otra parte, el uso de try..catch para detectar esta situación y suprimir el error, probablemente sería más simple - pero no exactamente una solución limpia.

+0

Main.js actualizado aquí: http://pastebin.com/Eiti2Nss Todavía recibo el error después de ejecutar 'cfx test'.Aún no he leído sobre la seguridad de subprocesos en la programación de complementos de Firefox, está en mi lista de tareas pendientes. – Pieter

+0

@Pieter: no hay seguridad de subprocesos, JavaScript tiene un único subproceso, a menos que cree un trabajador DOM explícitamente (sin relación alguna con los trabajadores de página que tiene en el SDK). –

+0

Entonces, ¿solo tengo que tener cuidado con las solicitudes asincrónicas y los temporizadores? De acuerdo con http://pastebin.com/ccx80iJV, una llamada a 'monitorWidget.postMessage (null)' todavía está causando problemas. – Pieter

0

Acabo de ver su mensaje en irc, gracias por informar de sus problemas. Se enfrenta a algún error interno en el SDK. He abierto un error sobre eso here.

Definitivamente debe conservar la primera versión de su código, donde envía mensajes al widget, es decir, widget.postMessage (en lugar de worker.postMessage). ¡Entonces tendremos que arreglar el error al que me he vinculado para hacer que tu código funcione!

Luego le sugiero que mueva el setInterval al toplevel, de lo contrario disparará el intervalo múltiple y la solicitud, uno por ventana. Este evento attach se activa para cada nueva ventana de Firefox.

+0

Si muevo el temporizador de actualización al nivel superior, ¿podría comenzar a disparar antes de que el widget se adjunte correctamente? Y si vuelvo a la primera versión, podría 'refreshUnreadCount()' encontrarse en una situación en la que se 'archiva' la Solicitud, el widget se destruye y luego el controlador 'onComplete' intenta llamar a' widget.postMessage', que ¿ya no está disponible? No sé cómo los subprocesos afectan a los complementos, así que no sé realmente qué pasaría. 'main.js' se vería como [this] (http://pastebin.com/MXEz4hnm) después de las actualizaciones. – Pieter

Cuestiones relacionadas