5

初めてアドオンを開発しています。ステータスバーに小さなウィジェットが表示され、未読のGoogleリーダーアイテムの数が表示されます。これに対応するために、アドオンプロセスは毎分Google Reader APIにクエリを実行し、応答をウィジェットに渡します。実行するcfx testと、次のエラーが発生します。

エラー:ページが破棄され、使用できなくなりました。

ウィジェットのdetachイベントをキャッチし、それに応じて更新タイマーを停止するようにしましたが、それでもエラーが表示されます。私は何が間違っているのですか?関連するコードは次のとおりです。

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

編集:プロジェクト全体をこのGitHubリポジトリにアップロードしました。

4

3 に答える 3

0

問題を報告していただきありがとうございます。ircであなたのメッセージを見たところです。SDKの内部バグに直面しています。私はここでそれについてのバグを開きました。

ウィジェットにメッセージを送信する、つまりwidget.postMessage(の代わりにworker.postMessage)コードの最初のバージョンを確実に保持する必要があります。次に、コードを機能させるために、リンクしたバグを修正する必要があります。

次に、setIntervalをトップレベルに移動することをお勧めします。そうしないと、ウィンドウごとに1つずつ、複数の間隔とリクエストが発生します。このattachイベントは、新しいFirefoxウィンドウごとに発生します。

于 2012-09-10T13:22:29.837 に答える
0

monitorWidget.postMessage()に電話をかけると、このメッセージが表示されると思いますrefreshUnreadCount()。明らかな原因は次のとおりです。refreshUnreadCount()ワーカーがまだアクティブなときにのみ呼び出すようにしますが、この関数は非同期要求を実行しますが、これには時間がかかる場合があります。したがって、このリクエストが完了するまでに、ワーカーはすでに破棄されている可能性があります。

1つの解決策は、ワーカーをパラメーターとしてに渡すことrefreshUnreadCount()です。次に、独自のdetachリスナーを追加し(要求が行われたときにそれを削除し)、要求の実行中にワーカーが切り離された場合は応答を無視することができます。

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

繰り返しになりますが、この状況を検出してエラーを抑制するために使用try..catchする方がおそらく簡単ですが、正確にクリーンなソリューションではありません。

于 2012-08-13T11:32:22.577 に答える
0

monitorWidget.port.emit("widthReported", response.json);この方法を使えば、イベントを発生させることができると思います。これは、コンテンツスクリプトおよびアドオンスクリプトと通信するための2番目の方法です。

于 2012-09-13T19:55:22.867 に答える