Hey all,
I’m trying to wrap my head around Unity’s coroutine system and I might be missing something here.
I am creating an SDK that interacts with a restful web service and I want to abstract away as much complexity from the end-user (developer) as possible.
My implementation works, but it just doesn’t sit right with me so I would value your input.
I have a generic GET function that calls a coroutine and returns the result via call back like this:
public ResponseResult Get(string path)
{
ResponseResult result = new ResponseResult();
StartCoroutine(Get_Coroutine(path, tmp =>
{
result = tmp;
}));
return (result);
}
}
static IEnumerator Get_Coroutine(string path, System.Action<ResponseResult> callback = null)
{
using (UnityWebRequest request = UnityWebRequest.Get(Settings.URI + path))
{
ResponseResult tmp = new ResponseResult();
request.SetRequestHeader("Content-type", "application/json");
request.SendWebRequest();
do { } while (!request.isDone); [COLOR=#0080ff]// This makes me cringe!![/COLOR]
tmp.Json = request.downloadHandler.text;
tmp.Error = request.error;
tmp.ResponseCode = request.responseCode;
tmp.Result = request.result.ToString();
callback(tmp);
yield return new WaitForEndOfFrame();[COLOR=#0080ff] // Found this in some code online for using callbacks in coroutine - pretty sure it should just return null though. [/COLOR]
}
}
Then in order to allow the user to just do a simple call to 'get whatever object they want I have simple methods like this:
public (Locale locale, ResponseResult responseResult) GetLocale ()
{
var result = Get("locale");
Locale locale = JsonUtility.FromJson<Locale>(result.Json);
return (locale, result);
}
The above example exposes a method to return a serialized ‘Locale’ object from the Json body of the webrequest. It also returns the responseResult object (tuple) to allow custom error handling not covered by the global error handler.
So firstly, I’m really uncomfortable having to use do { } while (!request.isDone); in GetCoroutine, but what I have read seems to indicate that my usage is correct and this is not blocking code. It just feels like a huge code smell to me. If I leave it out, the coroutine often returns without completing, resulting in no data.
More importantly though, does GetLocale () calling Get(string path) without doing so in its own coroutine cause thread blocks?
What about when the end-user calls GetLocale ()? The same question, does he need to call it in a coroutine?
I am really hoping to abstract away all complexity so would really like to avoid making the end-user use coroutines if possible.
Thanks for your time.
Dave