1

私は、オフィス全体の多数のディスプレイで使用されるRSSティッカーを作成しています。このRSSティッカーは、ツイッターフィードリーダー、天気ウィジェット、時計と連携して、すべて同じ.flaで実行されます。

これらのディスプレイはたくさんあるので、rss、twitter、天気データのためにそれぞれをオンラインにしたくありません。このデータはすべて、インターネットからダウンロードされるいくつかの単純なXMLファイルに含まれています。

サーバー上で実行されるWindowsサービスを作成しました。このサービスは、更新を監視し、新しいデータファイルをネットワーク上の共有にダウンロードするまでのすべての作業を実行します。次に、すべてのディスプレイのフラッシュダッシュボードに、ネットワークコピーから情報を取得させます。そうすれば、データは一度ダウンロードされ、他のすべてはこのローカルキャッシュにアクセスするだけです。

すべてが機能しますが、ランダムにRSSティッカーが機能しなくなります。これらのディスプレイにリモートでアクセスしてエラーログを確認する方法はありませんが、イーサネットケーブルを抜くと、ローカルのテスト環境でまったく同じ問題が発生します。ダッシュボードは、ネットワークRSSコピーにアクセスしようとして失敗し、接続が再確立された後でも、タイマーのティックごとに失敗し続けます。

切断を適切に待機し、ディスプレイが再接続したらRSSティッカーを再起動できるようにしたいと思います。これを行う方法がわかりません。以下は私のRSS関連のコードです。

// used to load a local xml file (stored in the same folder as the dashboard) that tells 
// the dashboards which RSS feeds can be found on the network, and where they are located. 
// It also contains the limits for how long each feed should be shown (both a time limit, 
// and a maximimum number of feed items)

var rssListXMLLoader:URLLoader = new URLLoader();
rssListXMLLoader.addEventListener(Event.COMPLETE, rssListXMLLoaded); 
rssListXMLLoader.addEventListener(IOErrorEvent.IO_ERROR, ioRSSListXMLLoaderErrorHandler);


// used to load the individual RRS feeds 

var rssFeedXMLLoader:URLLoader = new URLLoader();
rssFeedXMLLoader.addEventListener(Event.COMPLETE, rssFeedXMLLoaded); 
rssFeedXMLLoader.addEventListener(IOErrorEvent.IO_ERROR, ioRSSFeedXMLLoaderErrorHandler);


// rssListXMLData:XML and rssFeedXMLData:XML are used to store the XML data that is returned
// by the above loaders.

var rssListXMLData:XML = new XML(); 
var rssFeedXMLData:XML = new XML();

var currentRSSIndex:int = 2^10;
var currentFeedIndex:int = 2^10;
var currentLimit_Feeds:int = 2^10;
var currentLimit_Minutes:int = 2^10;
var limitStartTime:Number = new Date().time;
var gettingNewFeed = false;

// the blow Timer is used to keep the ticker moving. Each tick, it checks to see of the
// current RSS on sceen is has any text left. If it does, it removes the first letter
// causing the string to appear as if it is scrolling from right to left. If it has no
// more text, it gets the next feed.

var rssTickerTMR:Timer = new Timer(100, 0);
rssTickerTMR.addEventListener(TimerEvent.TIMER, updateRSSTicker);
rssTickerTMR.start();

updateRSSTicker();

function updateRSSTicker(e:Event = null):void
{
    if(ins_rssContent.text.length == 0)
    {
        if(!gettingNewFeed)
        {
            gettingNewFeed = true;
            getNewFeed();
        }
    }
    else
    {
        ins_rssContent.text = ins_rssContent.text.substring(1);
    }
}


// the below function checks to see if the RSS List is loaded. If it isn't it loads it,
// if it is already loaded, it calls the rssListXMLLoaded. This way, rssListXMLLoaded is
// never called unless the RSS List is already loaded.

function getNewFeed():void
{
    if (rssListXMLData == "")
    {
        trace("Loading RSS List XML");
        rssListXMLLoader.load(new URLRequest("rssFeeds.xml"));
    }
    else
    {
        rssListXMLLoaded();
    }
}


// the below function manages which feed needs to be used from the list.

function rssListXMLLoaded(e:Event = null):void
{
    if (e != null)
    {
        rssListXMLData = new XML(e.target.data);
    }

    currentFeedIndex++;

    if (
            currentFeedIndex >= rssFeedXMLData.channel["item"].length() || 
            currentFeedIndex >= currentLimit_Feeds || 
            new Date().time - limitStartTime >= (currentLimit_Minutes * 1000 * 60)
    )
    {
        limitStartTime = new Date().time;
        currentFeedIndex = 0;
        currentRSSIndex++;      
        currentRSSIndex = (currentRSSIndex >= rssListXML.children().length()) ? 0 : currentRSSIndex;        
        currentLimit_Feeds = Number(rssListXMLData.RSSFeed[currentRSSIndex].@limitFeeds)
        currentLimit_Minutes = Number(rssListXMLData.RSSFeed[currentRSSIndex].@limitMinutes)
    }
    try
    {
        rssFeedXMLLoader.load(new URLRequest(rssListXMLData.RSSFeed[currentRSSIndex])); 
    }
    catch(e:Error)
    {
        trace("whoops, try again");
    }
}


// the below function sets the text on the dashboard, and sets gettingNewfeed to false. This allows the
// rssTickerTMR:Timer to start removing the first letter of the newly added feed, causing the text to "scroll"

function rssFeedXMLLoaded(e:Event):void
{
    rssFeedXMLData = new XML(e.target.data);

    if (rssFeedXMLData.channel["item"].length() > 0)
    {
        var dateString:String = rssFeedXMLData.channel["item"][currentFeedIndex].pubDate;
        var date:Date = new Date(Date.parse(dateString.replace(" Z","")));

        if (date.toString() != "Invalid Date")
        {
            dateString = " @ " + FormatDate(date) + " " + FormatTime(date);
        }
        else
        {
            dateString = " @ " + dateString;
        }

        ins_rssTitle.text = rssFeedXMLData.channel.title + dateString;

        ins_rssContent.text = "                                                                        " 
                            + cleanDescription(rssFeedXMLData.channel["item"][currentFeedIndex].title) + "   - "
                            + cleanDescription(rssFeedXMLData.channel["item"][currentFeedIndex].description);

        gettingNewFeed = false;
    }
    else
    {
        ins_rssContent.text = "";
        gettingNewFeed = false;
    }
}

// removes the things from the RSS content that I don't want.

function cleanDescription(p_string:String):String 
{
    if (p_string == null) 
    { 
        return ''; 
    }

    var str:String = p_string.replace(/<\/?[^>]+>/igm, ''); //remove html tags.
    str = str.split("\r").join(". "); //replace line breaks with '. '
    str = str.replace("\t"," "); //replace tabs with a single space.
    str = str.replace(/(?:\.\s){2,}/g,". "); //replace multiple '. ' with a single one.
    str = str.replace(/((https?|ftp|gopher|telnet|file|notes|ms-help):
                          ((\/\/)|(\\\\))+[\w\d:#@%\/;$()~_?\+-=\\\.&]*)/igm, ' '); //replaces URL text with a single space
    str = str.replace(/#[\w]{3,}/igm,' ') //replaces hash tags with a single space
    str = str.replace(/\s{2,}/igm," "); //replace multiple spaces with a single space

    return str;
}

function ioRSSListXMLLoaderErrorHandler(e:Event):void
{
    trace("ioRSSListXMLLoaderErrorHandler:");
    trace(e.toString());

}


// the idea below is that it sets the text to "" and sets gettingNewFeed to false, which should get the
// rssTickerTMR:Timer to try to get a band new feed. Theoretically, it should try and fail over and again
// until the network is once again accessible. This doesn't work at all.

function ioRSSFeedXMLLoaderErrorHandler(e:Event):void
{
    trace("ioRSSFeedXMLLoaderErrorHandler:");
    trace(e.toString());

    ins_rssContent.text = "";
    gettingNewFeed = false;
}

誰かがこれにアプローチするためのより良い方法を知っていますか?皆様のご協力をよろしくお願いいたします。ありがとう!

編集!!!

Willが提案したように、私はタイマーベースのネットワーク監視サブシステムを作成しようとしました。RSSティッカーのIO_ERRORハンドラーで、RSSタイマーを停止し、ネットワーク監視タイマーを開始します。10秒ごとに、サーバーからファイルをダウンロードしようとします。それが機能するまでそれを続け、その時点でそれはそれ自身のタイマーをオフにし、RSSタイマーを再起動します。

理論的には機能するはずです。それだけでなく、ネットワークファイルの代わりにWebサイトをダウンロードするように変更すると機能します。ネットワークファイルを使用する場合、一度失敗すると、接続が再確立された後も失敗し続けます。これが私のコードです:

...

function ioRSSFeedXMLLoaderErrorHandler(e:Event):void
{
    rssTickerTMR.stop();
    networkMonitorTMR.start();

    trace("ioRSSFeedXMLLoaderErrorHandler:");
    trace(e.toString());

    ins_rssTitle.text = "Waiting for connection...";
    ins_rssContent.text = "";


}

// netowrk monitor
var networkMonitorXMLLoader:URLLoader = new URLLoader();
networkMonitorXMLLoader.addEventListener(Event.COMPLETE, networkMonitorXMLLLoaded); 
networkMonitorXMLLoader.addEventListener(IOErrorEvent.IO_ERROR, networkMonitorXMLLoaderErrorHandler);

var networkMonitorTMR:Timer = new Timer(10000,0);
networkMonitorTMR.addEventListener(TimerEvent.TIMER, checkNetwork);


function checkNetwork(e:Event = null):void
{
    networkMonitorXMLLoader.load(new URLRequest("//server/share/file.xml")); 
}

function networkMonitorXMLLoaderErrorHandler(e:Event = null) :void
{
    trace("Still Off");
}

function networkMonitorXMLLLoaded(e:Event = null) :void
{
    trace("Back On");
    rssTickerTMR.start();
    networkMonitorTMR.stop();
}

私が言ったように、「// server / shar / file.xml」をhttp://www.google.caに切り替えると、機能します。イーサネットを抜くとネットワークモニターが起動し、再度差し込むとRSSに戻ります...しかし、ネットワークリソースを使用すると、失敗し続けます...

4

1 に答える 1

2

この種の問題に対処する一般的なパターンは、接続が再確立されるまで接続をチェックし続けるタイムアウト メソッドを起動することです。ユーザーが気付かないように、バックグラウンドでこれを行うのが理想的です。あなたの場合、接続が失敗した場合 (IO_ERROR)、定義された時間の経過後に xml ファイルのダウンロードを再試行するメソッドにタイマーを設定します。失敗した場合は再設定してください。それまでの間、現在のアイテムを最初からもう一度表示し、新しいフィードがダウンロードされたら更新することができます。

于 2012-08-30T20:29:38.307 に答える