Idea: make async easier with "Then" event

  • 1 - agree with suggesting "cache"

    2 - please don't use "then" because It would confuse

    3 - will this new treak really optimise performance because we use webstorage generally on special even like game over or start of game when everything is not moving and activating so that will not affect a lot

    4 - any way thanks a lot but need more explainations

  • I like the sound of jayderyu's idea. It seems to make more sense and seems more flexible.

  • I agree with rexrainbow and jayderyu idea. It seems to be the better implementation considering I am storing and planning to continue a lot of data on webstorage and in the future, local storage.

  • I am not convinced, I mean would not that be exactly like using a dictionnary to store the keys while saving them? And if so, would that not compromise the whole point of it being asynchronous (Aka:whendealing with a lot of keys)?

    unless I misunderstood and you mean having basically a dictionary with a "Push to Local storage" action when needed, but even then, I feel something is not quite right..

  • No, I don't think a cache is a good idea. I previously considered it to keep it compatible with WebStorage, but decided not to for two reasons:

    • performance: the speed at which you can read and write values to the actual storage is proportional to the total amount of data in storage. So suppose you had 300mb of data in storage, and your app wants to read a single number, change it, then write the number back (e.g. a simple play count). That involves reading 300mb of data, plucking out a single value, then writing 300mb of data again.
    • it's always going to be unreliable: you can't really solve the problem of how to write the cache to the actual storage. At any time the user could just close the browser, and then there is no opportunity to do an asynchronous write to storage, and the changes in the cache are lost. There aren't any good options to mitigate that. Writing storage every time it changes will completely hammer performance (imagine writing 300mb every time any key changes), and throttling it to a timer means you can still lose data (e.g. if you write every minute, you can still lose up to a minute's worth of data).

    Besides you can do this yourself already if you really want to: just store the JSON data of a dictionary object in storage - but you'll probably have subtle and frustrating issues with data being lost randomly.

    I agree "Then" is a poor name... I think I'll go with "Next" for the time being.

    Reading Animmaniac's post, I think actually it could be a good idea to make "Next" act like "All completed", so it doesn't have the one-async-action limitation. The problem is then how to access multiple storage keys, but I think it could load multiple keys at once by a comma-separated list, e.g.:

    • Get item "level1score,level2score,level3score"


    • Set level1score to LocalStorage.ItemValue("level1score")
    • Set level2score to LocalStorage.ItemValue("level2score")
    • Set level3score to LocalStorage.ItemValue("level3score")

    This could of course use three separate "Get item" actions, but I think it's clearer with a comma-separated list: there's only one trigger that fires for the one action, instead of three triggers firing and "Next" only really triggering on the third, which could make it tricky to identify which values should be available to the ItemValue expression (since it should only make available values that the trigger is firing for).

  • Ashley

    "cache" is a small related data set. User picks this data set at the same time then read/write it (data in this set). Not to load whole storage data into cache imo. User could release it and reload new set manually.

    For writing action, each key-value is stored into different key of local storage, so that it does not write whole cache data into local storage, just one entry.

  • rexrainbow - but you still thrash the storage or lose data if you keep a cache in memory.

  • Ashley

    I could not get your point about writing.

    The writing action could be the same as local storage plugin. If the data had lose while using cache, it would be lose when using local storage plugin. Even "then" would lose them imo.

    The benefit of cache is to reduce the read complex.


    Writing action would update value in cache (memory) and also write it into local storage (disk).

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • rexrainbow - but it's confusing if the object looks like it is setting a value synchronously, but has only really cached it and it needs to be written asynchronously. For the caching system to perform well, you'd also have to have a per-key asynchronous write action. So to *really* write a value, you'd still need to do this:

    • Set "myKey" to "myValue" (only writes to cache)
    • Write "myKey" (writes for real and is asynchronous)

    On "myKey" set

    • (actions to run when done)

    This is even more complicated than the current system and is confusing to beginners since setting a local storage value does not actually persist it anywhere. If you want this, just implement a cache yourself: read and write to global variables, the Dictionary object, or anything else, and then write with Local Storage to save it.

  • [quote:3e7lt2rs]- Pathfinding could fire "then" after the path is found

    Doesn't it already work like that, "On path found"? What would be different or the benefit?

    [quote:3e7lt2rs]Does anyone have any thoughts about this? Good idea or bad idea? Perhaps there's an even better way it could be approached?

    Im not 100% sure I understand the benefit in this. Completely agree with the "When data loaded" kind of thing, which is very useful.

    But if you make a game and do a Async read of data, wont the data be to old when needed as you write the game will continue on. So when the data is actually need you would have to get it once more, in case it have changed.

    Wouldn't that leave two options, either you have to make sure that the data is there when you need it, so would require you to wait for it regardless of how it is read?

    The other one is that if you have a program that requires to load larger amount of data, you would wait for it to load. So you would put it at the start of layout or somewhere where you would wait for it to load, or it would be data that will not "impact" the game, so it wouldn't really matter if it was read as Async or not.

    But maybe I just misunderstood the benefits?

    As I see it the problem with Wait is that it just wait a specific time, which is fine for what it should be used for. But often it is used to "Trick" the code. Which is not nice I think. Whereas "Wait for signal" will allow the program to wait for something to be done or happen before moving on.

    So maybe a better idea is to just add more "Finalize triggers" to different things. Like you have "On path found" etc. It could be "On local data read", "On local data written", "On audio file loaded", "On video loaded" and so forth.

    Or is that not what you are trying to achieve with this?

    But regardless I do agree that "Then" is probably a bit confusing name. Then "Async. completed" or something might be better.

  • How about giving us a choice?

    1. Don't care about slight delay - start of layout, end of layout etc = synchronous.

    2. Writing/reading data in-game and don't want to cause a frame drop = asynchronous.

    I'm not a fan of Then, it will probably lead to beginner confusion.

  • - Set "myKey" to "myValue" (only writes to cache)

    - Write "myKey" (writes for real and is asynchronous)

    I agree with rex here - the only difference is I would drop the "write" action entirely. This proposed schema looks like many of the modern key-value storage schemas, which don't truly commit the data to disk until some time later, hence the term "eventually consistent". This shows that the proposed flow is a pattern (as opposed to an anti-pattern).

    The system as it is implemented now is close to the way it works in javascript, and I'm used to the async nature of js, but I believe it is very hard for beginners to grasp: remember some people have difficulty with arrays and some think variables are too hard. I'm not saying constuct should be designed solely for those people (lest we become like some other game-making software out there *cough*), but it should at least cater to them if it doesn't get in the way.

    The benefits of a "fake write" with posterior flush are reduced complexity for the dev (which is one of the strong suits of C2) and performance (since you don't have to wait to read values you just set). The only (slight) complication for you Ashley would be to ensure that writes issued in order get committed in order as well, and if there's a conflict, last write wins.

    It would be worth it to investigate how writes commit if the application crashes before receiving acknowledgement (different engines may do this differently). If it commits even without acks and "last write wins", as I suspect it happens, then there is no problem at all.

  • delete

  • Thanks for suggestion, I had made my first version of dictionary cache plugin.

    After loading cache completed, all read/write operations look likes synchronous.

    • Read had been done while cache loaded.
    • Writing actions in a tick would be fired at the same time ( in tick2() ). "Condition:On writing actions complete" will be triggered when all writing actions are done. User might wait this event or not.

    Data in local storage are-

    Sample capx , plugin.


    The reading and writing actions of local storage are embedded inside this plugin. So it does not need to work with official localstorage plugin.

  • Thanks rexrainbow for your plugin.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)