PDA

Volledige versie bekijken : rare uitvoering van script


Clemra
%Europe/Berlin %550 %2006, 13:12
Hallo,

Ik heb het volgende probleem. Als ik onderstaande script uitvoer verwacht ik als trace:

1
2
3
4

Het blijkt nu dat terwijl de oCallBack.onResult gewoon nog wacht tot hij een result krijgt de script verder gaat!

Ik heb al geprobeerd dit in een try/catch te gooien maar dat hielp ook niet.

Voor de duidelijkheid, ik wilt pas dat de Initialize() functie wordt uitgevoerd nadat alles binnen de InitApplication() klaar is.

Kan iemand mij mee helpen?

alvast bedankt


---------- code ---------------
import mx.services.*
import flash.external.*

class Settings
{
private var ErrorRaised:Boolean;

public var addEventListener:Function;
public var removeEventListener:Function;
private var dispatchEvent:Function;

public function Settings()
{
InitApplication()
Initialize()

}

public function InitApplication():Void{
//webservice aanroepen
var WebServiceLocation:String = "http://localhost:3406/WebServiceTest1/Service.asmx?wsdl";
var Service:WebService = new WebService(WebServiceLocation)

Service.onFault = function(fault){
throw new Error("Error bij het maken van een connectie met de initWebservice")
ErrorRaised = true;
}
trace("1");
Service.onLoad = function(){
trace("2");
var oCallBack:Object = Service.InitApplication();
oCallBack.onResult = function(initApp:Boolean):Void
{
_root.GetValue(initApp)
if(!initApp)
{
trace("test"+initApp);
}
}
}
trace("3");
}

public function Initialize():Void{
trace("4");

}

}
---------- END code ---------------

BernardV
%Europe/Berlin %674 %2006, 16:10
Gewoon je Initialize() aanroepen in de onResult.

Want het script gaat niet wachten op een result voor de verdere uitvoer.

Clemra
%Europe/Berlin %684 %2006, 16:26
Gewoon je Initialize() aanroepen in de onResult.

Want het script gaat niet wachten op een result voor de verdere uitvoer.

Dat is inderdaad een oplossing. Maar het moet toch wel mogelijk zijn om je script synchroon te maken zoals dat met programmeertalen kan?

Het plaatsen van me Initialize() in me onresult lost het voor nu op. Op het moment dat ik binnen die onresult meerdere functies krijg die ook synchroon moeten lopen krijg ik weer hetzelfde gezeik.

BernardV
%Europe/Berlin %710 %2006, 17:02
Dat is inderdaad een oplossing. Maar het moet toch wel mogelijk zijn om je script synchroon te maken zoals dat met programmeertalen kan?

Hoe bedoel je dat?
Want het lijkt me niet logisch dat je script volledig gaat hangen terwijl je wacht op een request naar een server. Dat vang je op met events, zodra iets binnen is dispatch je een event en elke listener gaat dan zijn werk doen.

Dauntless
%Europe/Berlin %728 %2006, 17:29
Dat is inderdaad een oplossing. Maar het moet toch wel mogelijk zijn om je script synchroon te maken zoals dat met programmeertalen kan?

Het plaatsen van me Initialize() in me onresult lost het voor nu op. Op het moment dat ik binnen die onresult meerdere functies krijg die ook synchroon moeten lopen krijg ik weer hetzelfde gezeik.
Flash kent alleszinds geen Treads, als dat is wat je bedoelt ?

Clemra
%Europe/Berlin %742 %2006, 17:48
Ik ben gewend dat mijn script in bijv. asp.net stap voor stap gaat. Zoals ik het nu zie voert flash meerdere scripts tegenlijk uit. Moet ik hier gebruik gaan maken van listeners?

Ik heb btw voor de gein Initialize() aanroepen in de onResult. Dat werkte dus niet, na lang zoeken heb gevonden dat andere mensen dit oplossen met delegat.create oplossen. Dit werkte ook niet. Als ik het buiten de onResult plaats doet hij het btw wel.

BernardV
%Europe/Berlin %751 %2006, 18:02
Zo gaat het denk ik wel werken met Delegate.

Kan het niet voor je testen ;)


import mx.services.*;
import flash.external.*;
import mx.utils.Delegate;

class Settings
{
private var __errorRaised:Boolean;

private var __service:WebService;
private var __webServiceLocation:String = "http://localhost:3406/WebServiceTest1/Service.asmx?wsdl";

public var addEventListener:Function;
public var removeEventListener:Function;
private var dispatchEvent:Function;

public function Settings()
{
initApplication();
}

public function initApplication():Void{
__service = new WebService(__webServiceLocation);
__service.onFault = Delegate.create(this,serviceFault);
__service.onLoad = Delegate.create(this,serviceLoad);
}

private function serviceLoad():Void
{
var oCallBack:Object = __service.InitApplication();
oCallBack.onResult = Delegate.create(this,callBackResult);
}

private function serviceFault(fault:Object):Void
{
throw new Error("Error bij het maken van een connectie met de initWebservice");
__errorRaised = true;
}

private function callBackResult(initApp:Boolean):Void
{
_root.GetValue(initApp);
trace("Callback result:" + initApp);
if(initApp) initialize();
}

private function initialize():Void{
trace("initialize() is called");
}
}

Ik heb trouwens je Hoofdletter gebruik aangepast ;)

Ik gebruik nooit hoofdletters voor functies, behalve bij de constructor. Hetzelfde voor variabelen, omdat Hoofdletters voor mij Classes zijn en geen variabelen.

Dauntless
%Europe/Berlin %761 %2006, 18:16
@Clemra: Lees eventueel dit: (oa. over het hoofdlettergebruik)
http://www.adobe.com/devnet/flash/articles/as_bestpractices.html

Clemra
%Europe/Berlin %771 %2006, 18:31
Wow!

Onwijs bedankt voor jullie snelle reactie.

Ik heb het nog niet kunnen testen, dat zal ik vanavond doen.

Ik weet wel dat het zo veel beter uitziet ;)
@Dauntless: Bedankt voor je link man! Je hebt gelijk, het is van belang om op je schrijfwijze te letten. Maak het voor jullie ook een stuk makkelijker wanneer ik weer een vraag heb :D

Ik zal hier posten of het zo werkt!

Clemra
%Europe/Berlin %922 %2006, 22:08
Super! Hij doet het, onwijs bedankt!

Clemra
%Europe/Berlin %411 %2006, 09:52
hoi,

__service.InitApplication() roept nu in mijn webservice een functie aan die simpelweg een true terug geeft. Is het zo te maken dat ik met (volgens mij ) Eventlisteners zoiets kan zeggen als

if(initApplication){
...

Dus dat ik de boolean kan gebruiken en dat ik niet meerdere callbacks hoef te maken om die boolean terug te krijgen?

BernardV
%Europe/Berlin %419 %2006, 10:04
Kun je misschien iets duidelijker zijn en eventueel wat voorbeeld code posten?

Doel je op?

var oCallBack:Object = __service.InitApplication();
oCallBack.onResult = Delegate.create(this,callBackResult);

Clemra
%Europe/Berlin %429 %2006, 10:18
ok, nou met de (mooie) code die van vrijdag van je kreeg kan ik in mijn .fla nu zeggen. mySettings.InitApplication(). Binnen de classe worden de functie netjes aangesproken en ik krijg uiteindelijk met de oCallBack een trace met de juiste resultaat die mijn webservice teruggeeft. Ik wil nu binnen mijn .fla de webserviceresultaat terugkrijgen.

Dus zoiets als

var initVar:Boolean;

initVar = mySettings.InitApplication()

of dat ik het zelfs binnen een if kan gebruiken:

if(mySettings.InitApplication()){
..

Is dit nu wel wat duidelijker wat ik bedoel?

BernardV
%Europe/Berlin %449 %2006, 10:46
ja dat is iets duidelijker :)

Dat kun je inderdaad doen met de EventDispatcher alleen niet helemaal zoals je hier schetst.

In de constructor van Settings zul je de EventDispatcher moeten initialiseren:

EventDispatcher.initialize(this);


En dan (neem ik aan) in de initialize() functie een Dispatch als het gelukt is en in callBackResult een dispatch als "initApp" false is.

Je zou daar iets als dispatchEvent({type:"onServiceLoaded",data:true}); kunnen gebruiken (false voor een mislukte aanvraag).

Dan in je fla op de settings.

var listener:Object = new Object();
listener.onServiceLoaded = function(evt:Object){
trace(evt.data);
}
settings.addEventListener(listener);
settings.initApplication();


Dan wordt de onServiceLoaded functie uitgevoerd zodra het event gedispatched wordt. Je kunt niet een true/false waarde returnen in initApplication, omdat deze niet weet of de aanvraag naar de service is gelukt.
Daar kun je alleen returnen of de WebService goed is aangemaakt, maar of deze ook daadwerkelijk werkt niet.

Hoop dat dit een beetje duidelijk is.

Succes!

//Edit foutje in de listener code ;)

Clemra
%Europe/Berlin %474 %2006, 11:23
hoi,

Ik had het al voor elkaar met de oude manier van callbacks (this.onServiceLoaded) maar jouw manier is de nieuwe manier van callbacks. Het werkte btw niet direct het plaatsen van de addEventListener werkte bij mij als volgt:

mySettings.addEventListener("onServiceLoaded",listener);

nogmaals onwijs bedankt ;)

Clemra
%Europe/Berlin %515 %2006, 12:23
ok,

De verbinding en de initApplication gaat goed.

Ik heb nu een functie aangemaakt in mijn webservive die createXML() heet en deze returned een XML object.

Nu krijg ik bij het aanroepen van de functie [webservicesURL]/methodenaam de melding

"Error opening URL "http://localhost:3406/WebServiceTest1/Service.asmx"

terwijl ik met een breakpoint binnen visual studio wel binnen de functie kom en zie dat hij netjes returned

de code die ik gebruik voor het loaden van de xml is:

public function getXml()
{
trace("function getXml()");
_xmlResult = new XML;
_xmlResult.ignoreWhite = true;
_xmlResult.load(http://localhost:3406/WebServiceTest1/Service.asmx/createXML);
_xmlResult.onLoad = Delegate.create(this, showXML);
}

Ik heb me dus suf gezocht en het grote handboek erbij gepakt en die geven allemaal hetzelfde code terug als voorbeeld.

Het rare merk ik nu dat als ik op invoke klik ik wel netjes de xml zie en als ik de url daarvan copy/paste in een nieuw scherm zegt tie dat de pagina niet bestaat.

Kan dit liggen aan dat ik geen gateway gebruik ofzo?

Hebben jullie misschien een idee wat er fout gaat?

BernardV
%Europe/Berlin %667 %2006, 16:01
Gebruik eens de onError handlers van XML en kijk daar eens wat de daadwerkelijke fout is. Misschien heb je te maken met een security probleem.

Het kan ook zijn dat flash na een bestand de /createXML niet goed pakt, die zie ik namelijk niet terug in je foutmelding. Is het ook mogelijk deze aan te roepen met ?createXML ? Dan zou je dat eens kunnen proberen.

Clemra
%Europe/Berlin %909 %2006, 21:49
ik heb met een beetje kloten ongeveer gevonden waar het aan ligt. Op het moment dat je je webservice build en je functie selecteerd kun je die ook "invoken". Je functie wordt dan correct aangesproken ( je kunt hem debuggen namelijk) en er komt bij mij correct XML uit.

Je ziet dan dat het url "http://localhost:3406/WebServiceTes....asmx/createXML" is. Als je deze in een nieuw scherm opent krijg je een Error dat. Ik ben er nu achter dat het url gepost dient te worden.

Enig idee hoe ik dit moet aanpakken met een xml.load?

BernardV
%Europe/Berlin %412 %2006, 09:54
Ik weet zo niet of je met een AddRequestHeader een POST kunt nabootsen.
Wat wel kan is de sendAndLoad optie gebruiken van XML, die request wel met POST ipv GET. Dan zou je gewoon een leeg XML object kunnen zenden en dan de request gebruiken.

Clemra
%Europe/Berlin %497 %2006, 11:55
Nou dat is inderdaad wat ik gedaan heb. Ik kwam eigenlijk alleen even de code plaatsen hier voor andere mensen die dit ook tegen komen.

Dit is wat ik uiteindelijk heb moeten gebruiken om een xmldocument terug te krijgen en deze direct uit te kunnen lezen. Er staat een onData in wat totaal niet logisch is maar als ik die weghaal doet hij het niet.

public function getWebserviceXml(webServiceXMLLocation:String, sendVar:LoadVars)
{
trace("function getXml()");

var myXML:XML = new XML();
myXML.ignoreWhite= true;

sendVar.onData = function(rawXML)
{
//DIT MOET ERIN BLIJVEN ZITTEN!!
}

myXML.onLoad = function(success:Boolean) {
if (success) {
trace("load");
// Retrieve the title of the first node in the path /rss/channel/item/title.
var titleNode:String = XPathAPI.selectSingleNode(this.firstChild, "/settings/var/name");
trace(titleNode.toString());
} else {
trace("XML loading failed !!!");
}
};
//Er wordt gebruik gemaakt van sendAndLoad omdat er een POST moet plaatsvinden bij de webservice
sendVar.sendAndLoad(webServiceXMLLocation,myXML, "POST")
}



Je ziet een sendVar wat als loadVar is aangemaakt. Het mooie van deze is dat je in je functie bijv een byval id kunt aanmaken en je voor de sendAndLoad kunt zeggen
sendVar.id = 1001 ofzo. Deze wordt dan netjes opgevangen in je functie.

Omdat ik deze functie dynamisch wil gebruiken zou ik graag die myXML.onload los willen halen en daar een Delegate.create voor willen gebruiken. Maar hoe stuur ik dan de success:Boolean mee?

BernardV
%Europe/Berlin %536 %2006, 12:52
De success boolean wordt standaard meegestuurd.


myXML.onLoad = Delegate.create(this,xmlLoaded);

function xmlLoaded(success:Boolean):Void
{
trace(success);
}


Alle attributen die een functie heeft, krijgt de delegate ook.

Ik gebruik zelf deze aangepaste versie van Delegate:

class util.Delegate
{
public static function create(target:Object, handler:Function):Function
{
var extraArgs:Array = arguments.slice(2);
var delegate:Function;
delegate = function () {
var fullArgs:Array = arguments.concat(extraArgs, [delegate]);
return handler.apply(target, fullArgs);
};
return delegate;
}
}

Het voordeel van deze is dat je ook extra attributen kunt meegeven, wat de standaard Delegate negeert.

voorbeeldje:

import util.Delegate;

myMovie.onRollOver = Delegate.create(this,showMovie,true);
myMovie.onRollOut = Delegate.create(this,showMovie,false);

function showMovie(b:Boolean):Void
{
mySecondMovie._visible = b;
}


De true/false waarde wordt hier meegegeven aan de functie, dit is niet mogelijk met de MM Delegate.