Use Shared Object Data() or Shared Object Property() to store value - actionscript-3

I'm confused. SharedObject seems have two ways to store value in it, by data and setProperty():
so.data.foo = 'bar';
so.setProperty('boo', 'bar');
What's the different? And why doesn't it have getProperty()?

From the SharedObject reference: setProperty() marks a property as "dirty" in addition to setting it, which you need to do if you're using a remote SharedObject, as it tells the server that the value needs to be updated in other clients.
It's slightly more convenient than manually setting the property and then calling setDirty(), and there's obviously no need to for a similar getProperty() method, as the server doesn't need to be informed when you do that.

Related

Alternative to global variables

Hi I am doing a simple script where I want to track what step I am up to and use the result from a button click handler.
1)I cannot pass the variable as it is an event
2)Cannot use global variables as they seem to be constants only once set
Is there any way to set and object or variable multiple times and access the current value from within a handler function?
Found several examples suggesting a hidden widget, as well as that being a poor solution I also struggled to retrieve the value once set. IE it had a .setValue but no .getValue
Help please this is not a difficult thing in any other language I have tried but new to GAS
Cheers
There are more options - one, as you mentioned is to use a hidden widget. Although there is no .getValue(), it can be accessed through e.parameter within the click handler.
Two, for small amounts of data, you can use ScriptProperties / UserProperties and CacheService
Third, you can use the script DB or a spreadsheet if you are dealing with large amounts of data.
Having said all this, it would be better if you can post some code of what you're trying to achieve. Many times, code speaks louder than words.
Private Cache is intended for this type of thing https://developers.google.com/apps-script/reference/cache/

Which objects to make global, which to make local?

To avoid the moderators who don't like general questions, this is a Visio VBA one but I didn't want to include that in the title as it's a bit niche, and I guess the answer might be generic :-)
My code has the following variables:
Public gappVisio As Visio.Application
Public gdocFile As Visio.Document
Public gpagDiagram As Visio.Page
For those unfamilar with Visio, you create an application object, open the document, then set a reference to a page in the document where you can actually do some drawing.
All vars are global, but actually gdocFile is only used in my initialisation routine.
So my question is, do I need gdocFile as global, or can I just make it local?
I suppose I was worried that if it was local when it went out of scope it might tidy up the Document object, but I still need the page of the document?
Does that make sense?
Don't make a variable or object global unless you absolutely have to, which is almost never. Pass object references as parameters to those procedures that need them -- and only to those. Anything you need from the object before it "runs out of scope", as you say, should be passed to the calling procedure as Function return value (or, more obscurely hence less preferably, Sub ByRef parameter value).
When you say an object is out of scope, it's actually the reference to that object that is out of scope. The object still exists unaltered in memory.
Generally, global is bad and leads to difficult-to-maintain code, but exceptions could be things like universal constants, e.g.
Public Const PI As Double = 3.14159265358979
It's fine to have that as global.
In your case, the document lifetime is controlled by Visio application, the doc will not get cleaned up, no matter how many variables which refer to it you create, or in which scopes they are (global or local). Means, all reference counting (scoping) rules are simply ignored by Visio for documents in fact - the doc is not destroyed, even if there are no more references to it from your code.
You can tell Visio to close the document using document.close. After that call, any attempt to use document's (or page's) methods or properties using any of doc/page variables referring this document/page in this document will result in exception.
A doc may be closed by user. In this case all variables referring to it (or objects inside of it, such as pages or shapes) will become invalid.

What is __AS3__?

Sometimes in debug mode with Flash Builder, I see something like
__AS3__.vec.Vector.<Object> (#909e219)
but when I try to store this variable in another as3 variable, Flash duplicate this variable. Concretly, I'm trying to exclude some values on dragInitiator.selectedItems property before adding them to a List but when I use splice method on it, values aren't deleted from this vector.
So how can I acces variable with __AS3__ namespace please ?
According to a Tamarin developer:
The namespace "__AS3__.vec" is an artifact of a time when we did not have good API
versioning and could not introduce new top-level names without the risk of breaking
existing code. Today we would probably have made "Vector" public & versioned.
Source: http://hg.mozilla.org/tamarin-redux/rev/817f3e019ba2#l2.30
In other words, __AS3__ is the package where are defined Flash internal classes into Tamarin VM.
To access such variables, you don't need to specify the namespace. You only have to use the FQN declared in playerglobals.swc.

SharedObject and Dictionary problems in Flash Builder

I'm usin Flash Builder to create some actionscript code that uses SharedObjects.
First question: how can I delete my local SharedObject in Flash Builder? I am debugging my program and the SharedObject sems to persist between runs. I want to start fresh and clean with no SharedObject storing my data. How do I get rid of it?
Also, in my SharedObject, I used mySharedObject.data["mykey"] to store a Dictionary. This Dictionary will have String keys and values of MyCustomClass. The problem is that when I later try to loop over the values of this Dictionary, I get error #1034 cannot convert object to type MyCustomClass. It seems like I can put an item of type MyCustomClass into this dictionary, but I can't get the item back out as anything other than an object.
Any idea what is going wrong?
Those are essentially two questions, so should have been asked as two questions. Anyway, I'd answer them here but still prefer that you break them up in two parts (possibly leave a link to the other one here for reference sake):
Local shared object, are useful exactly for persistence across runs. And then there's SharedObject.clear() to clear the state as required.
For you second issue, Shared Object's serialize your object into AMF, so that it can be written to disk or sent over network using RTMP. Now, your custom class can't really be serialized in AMF. What actually happens is that the public properties (and dynamic ones, if the class is declared dynamic) are serialized into the structure. So, the public data is stored... but it's essentially a general Object.
To work around that, you can have a public static readFrom(object:Object):MyCustomClass type function, which would read the properties from the passed object to construct a new MyCustomClass representing that information.
There are ways to register your class with the player to be stored in SharedObject (see here)... but you need to make sure that the code that de-serializes that data is aware of the class as well.
To make a class available for conversion, in your global initialization use registerClassAlias() call with MyCustomClass and its fully qualified name as parameters. The manual. Say your custom class is foo.bar.TheClass, you write:
registerClassAlias('foo.bar.TheClass',foo.bar.TheClass);
In order to drop old SO use delete call against so.data["mykey"] and do so.flush(). Edit: SharedObject.clear() is way better.
1/ Being persistent is one of the particularity of a SharedObject. To cleanup all its content, you need to call the clear method.
var shareObject:SharedObject = SharedObject.getLocal('justatest');
shareObject.data.test = 'test';
trace(shareObject.data.test)
shareObject.clear();
trace(shareObject.data.test)
output
test
undefined
2/ To store complex data types in SO, you need to use flash.net.registerClassAlias (example here)

How can I save a global variable value after dynamically loading a reference?

I have a Access 2003 database that will dynamically load MDB databases as a library reference. The reason for this is this database is a menu front-end for 60+ application databases. Rather than deal with permanently referencing all these databases, the menu front-end will dynamically reference what is needed when the user makes a selection. I was working on moving this database to Access 2010 and creating a custom ribbon. I started using the technique from here to capture the ribbon object in a global variable when the ribbon loads. I then ran into the problem where I could verify the code was running and the global variable was correctly being assigned the ribbon reference but after the database would run through it's startup routine, that global variable would get reset to Nothing.
To verify what was going on, I created a simple database for testing. In this database, I had a module with a global variable:
Public obj as Object
I then had a function like this:
Public Function SetObj()
Set obj = Application
Debug.Print "IsNothing=" & (obj Is Nothing)
References.AddFromFile "Test.mdb"
Debug.Print "IsNothing=" & (obj Is Nothing)
End Function
Obviously, in my code, "Test.mdb" refers to an actual file. If I run this code, Debug.Print gives me "IsNothing=False" for both instances, but after the function finishes and if I wait a couple seconds, Debug.Print will give me "IsNothing=True". If I comment out References.AddFromFile, Debug.Print gives me "IsNothing=False" no matter how long I wait.
It makes sense to me that since Access has to re-compile the VBA code after loading the library that all global variables are reset. I've experimented with moving the global variable into a class, but since I then need a global variable for the class, the class variable then gets reset instead. I tried using a local variable in the function to save the value of the global variable, but it looks like Access waits a couple seconds after the code is finished running to do the re-compile, so that doesn't work either. Does anyone have any other ideas to accomplish this?
I don't really know if this will solve the problem for this kind of reference, but in general, I don't use public variables for this kind of thing, but instead use a STATIC variable inside your function. It would be something like this:
Public Function SetObj() As Object
Static obj As Object
If (obj Is Nothing) Then
Set obj = Application
End If
Set SetObj = obj
End Function
Then you'd just use SetObj as an object for using your application. In a production app, you'd need tear-down code, too, but I've omitted that here.
I doubt this helps, but your code struck me as rather inefficient and incomplete.
I figured out a solution to my problem, and thanks #David-W-Fenton, as your answer gave me the idea. I use your approach in a library database for caching frequently-accessed values that are stored in a table but don't change after the initial startup. Those values aren't lost every time the references change, and that's when the light bulb lit up.
The solution is to put the global variable in a library database. Access looks to be only resetting global variables in the database that the reference is being loaded into - which makes sense after thinking about it. So since the library database isn't the one being re-compiled, it doesn't get it's global (or private or static) variables reset.
What I ended up doing was creating a new module in an existing library database. It has a private variable and two methods - one to set the variable, one to retrieve the variable value. In my menu front-end database, when the ribbon loads and calls my callback function, rather than saving the ribbon object in the front-end database, I pass it to this module for saving. I now no longer lose that ribbon reference whenever new databases are added to the library references on the fly.