Reputation: 11
It would seem to be a simple question, but I can't find an answer to it.
I have a program in Unity that saves data locally using standard unity functions PlayerPrefs.SetInt
and PlayerPrefs.GetInt
.
I want to change saving data from a local computer to saving on a web environment. There is an API and functions for saving on Web. I want to make function that have similar syntax, for example, myPlayerPrefs.SetInt
and myPlayerPrefs.GetInt
.
But, API dial with the Web asynchronous, and to get a value from the Web, I need to use the Callback function.:
APIController.WebAppStorageGet(key, callback);
For example
APIController.WebAppStorageGet(key, (value) => { Debug.Log( value);});
Other example how functions work
// save data
APIController.WebAppStorageSet("score", 5);
// get data
APIController.WebAppStorageGet("score", (value) => { Debug.Log( value);});
The result on the console will be 5
How can I create a class and function:
m_Score = myPlayerPrefs.GetInt("score", 0);
Based on function
APIController.WebAppStorageGet(key, callback);
If I do like this get 0:
public static async Task<int> GetInt(string key, int fallback = 0)
{
int intvalue = fallback;
APIControler.WebAppStorageGet(key, (strvalue) => {
intvalue = int.Parse(strvalue);
});
return intvalue;
}
Upvotes: -2
Views: 44
Reputation: 90814
As mentioned before you can't/shouldn't simply force asynchronous code into a synchronous code pattern. Personally I see nothing wrong in having a callback and handle the result event driven.
The closest alternative would be a Task<int>
as you tried - but if course you have to actually wait for a result before returning the fallback value ;)
So if there is no way to modify the given API signature itself you could wrap it into a proper async Task like e.g.
public static async Task<int> GetInt(string key, int fallback = 0)
{
var completionSource = new TaskCompletionSource<int>();
try
{
APIControler.WebAppStorageGet(key, strvalue =>
{
var value = int.Parse(strvalue));
completionSource.SetResult(value);
}
}
catch
{
// you could of course also be more fine grained here
// and do the fallback only if the API answers with an "expected" error
// and rather do a SetException here
completionSource.SetResult(fallback);
}
completionSource.Task;
}
Read more about TaskCompletionSource
!
if you really wanted you could of course also freeze up the main thread until you receive a value - probably not recomendable, but since you specifically asked for it
public static int GetInt(string key, int fallback = 0)
{
var completionSource = new TaskCompletionSource<int>();
try
{
APIControler.WebAppStorageGet(key, strvalue =>
{
var value = int.Parse(strvalue));
completionSource.SetResult(value);
}
}
catch
{
// you could of course also be more fine grained here
// and do the fallback only if the API answers with an "expected" error
// and rather do a SetException here
completionSource.SetResult(fallback);
}
var task = completionSource.Task;
// This forces the current thread to wait until there is a result for that task
return task.Result;
}
Could of course use direct while
loop waiting for a flag to be set etc - there are multiple ways - but first of all I already had the completionSource code at hand and am lazy ^^ and second going through Task.Result
is a good way to make the thread wait without using a CPU heavy while
loop
Upvotes: 0