You have designed your “SendAPIRequest” method as a blocking request. This doesn’t work as per definition a blocking request blocks until it finishes. So it’s impossible for your method to actually return a JSONNode if you want it non-blocking. This piece of code will block until the www request is done:
while (!theWWW.isDone)
{
// meanwhile //
}
All your main thread does while the request is pending is running this one single loop. Unity can not continue if you don’t give the control back to Unity.
Any asynchronous tasks that run in the background need to use some sort of producer - consumer pattern or use callbacks to handle the data once it has finished loading. Generally callbacks are the most simple solution. Though if you have really large amount of json text, the parsing could cause some performance problems as well. In this case you could do the parsing on a seperate thread (as far as i remember SimpleJSON should work on a seperate thread). In case of using threads for parsing you have to use some sort of thread-safe buffer to hand over the result from the loading thread to the main thread.
We don’t see what you actually do with the parsed json data. However the general pattern with callbacks would look something like this:
private void SendAPIRequest(string aUrl, string aRequest = "{}", System.Action<JSONNode> aCallback)
{
StartCoroutine(aUrl, aRequest, aCallback);
}
IEnumerator LoadJSON(string aUrl, string aRequest = "{}", System.Action<JSONNode> aCallback)
{
UnityWebRequest www = UnityWebRequest.Post(url, request);
www.SetRequestHeader("Content-Type", "application/json");
www.SendWebRequest();
yield return www;
var responseData = www.downloadHandler.text;
JSONNode response = JSON.Parse(responseData);
if (aCallback != null)
aCallback(response);
}
Now you can actually “send” an API request and get a callback when it finishes. Like that:
SendAPIRequest("https://my.server.tld/path", yourRequestData, (response)=>{
// do something with the "response"
});
Note that you don’t have to use a lambda expression / anonymous delegate. You can simply use an ordinary method like this:
SendAPIRequest("https://my.server.tld/path", yourRequestData, OnApiRequestDone);
// [ ... ]
void OnApiRequestDone(JSONNode aResponse)
{
// do something with the "aResponse"
}
This is exactly the same. “OnApiRequestDone” will be called once the coroutine has finished loading the data from the server and directly passes on the parsed JSONNode.
Keep in mind that at the moment there’s no error handling inside this simple coroutine. Usually you want to check if the request was successful (maybe no internet connection? maybe server down?) and communicate that result accordingly. There are generally two ways you can handle this. Some prefer to use two seperate callbacks. One for handling the successful request and one to handle the failure. The other solution is to put the success information into the json result and handle everything in that single callback. Most APIs which use JSON already have some sort of “success” indicator inside the response. So if the request didn’t go through at all you can simply generate your own “failure” response which can be handled in the callback.