2012-08-30 5 views
1

나는 사무실 밖에서 많은 수의 디스플레이에 사용되는 RSS 티커를 만들고있다. 이 RSS 티커는 Twiter 피드 리더, 날씨 위젯 및 시계와 함께 모두 동일한 .fla로 실행됩니다.UrlLoader를 사용할 때 임시 네트워크 문제를 어떻게 관리합니까?

이러한 디스플레이가 많기 때문에 각자 온라인, rss, twitter 및 weather 데이터를 얻는 것을 원하지 않습니다. 이 모든 데이터는 인터넷에서 다운로드되는 여러 가지 간단한 XML 파일에 포함되어 있습니다.

Google 서버에서 실행되는 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][email protected]) 
     currentLimit_Minutes = Number(rssListXMLData.RSSFeed[currentRSSIndex][email protected]) 
    } 
    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; 
} 

이 접근 방법에 대해 더 잘 알고있는 사람이 있습니까? 여러분 모두가 제공 할 수있는 도움을 주시면 감사하겠습니다. 감사!

EDIT !!!

Will이 제안한대로 타이머 기반 네트워크 모니터링 하위 시스템을 만들려고했습니다. 내 RSS Ticker의 IO_ERROR 처리기에서 RSS 타이머를 중지하고 Network Monitoring Timer를 시작합니다. 10 초마다 서버에서 파일을 다운로드하려고 시도합니다. 그것은 작동 할 때까지 그렇게 계속되며, 타이머가 꺼지면 RSS 타이머가 다시 시작됩니다.

이론적으로 작동해야합니다. 뿐만 아니라 네트워크 파일 대신 웹 사이트를 다운로드하도록 변경하면 작동합니다. 네트워크 파일을 사용할 때 실패하면 연결이 다시 설정된 후에도 계속 실패합니다. 여기 내 코드입니다 : 내가 말했듯이 내가 http://www.google.ca에 "//server/shar/file.xml"을 전환하는 경우,

... 

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

, 그것을 작동합니다. 이더넷 연결을 끊으면 네트워크 모니터가 시작되어 다시 연결하면 RSS로 다시 전환되지만 ... 네트워크 리소스로 인해 계속 실패합니다 ...

+0

networkMonitorXMLLoaderErrorHandler에 중단 점을 넣고 작동이 예상되면 변수 패널에서 이벤트의 속성을 확인하십시오. 로컬 대신 인터넷 URI를 사용할 때 일종의 보안 오류가 발생하는 것 같습니다. 하나. – shaunhusain

답변

2

처리 할 일반적인 패턴 이러한 종류의 문제는 다시 설정 될 때까지 연결 상태를 계속 확인하는 시간 초과 메서드를 실행하는 것입니다. 이상적으로는 사용자가 알지 못하도록 백그라운드에서이 작업을 수행하는 것이 좋습니다. 귀하의 경우, 연결에 실패하면 (IO_ERROR) 타이머를 정의 된 시간 후에 xml 파일 다운로드를 다시 시도하는 메소드로 설정하십시오. 실패하면 다시 설정하십시오. 그 동안 처음부터 다시 현재 피드를 표시하고 새 피드가 다운로드되면 업데이트 할 수 있습니다.

+0

제안 사항을 구현했으며 네트워크 파일을로드하는 중 문제가 있음을 발견했습니다. 그것은 인터넷 다운로드와 잘 작동합니다.자세한 내용은 내 편집 된 anser를 참조하십시오. 이걸 도와 줘서 고마워! – Chronicide