How to make a script wait for a UnityWebRequest to finish for WebGL without a coroutine?

Hello!

I’m writing code that goes out to an API and gets data in JSON, I have created classes to use the JSON utility to decode this JSON. Therefore(As far as I’m aware) I need to use a method instead of a coroutine to return the data that I get from the JSON decode. So in order to make the method wait for the UnityWebRequest to finish, I was using a while method. I found out that it will make the WebGL freeze, So I’ve been trying to find a way to make it wait without using a coroutine.

**Here’s My Code: **

    public TaskList FindTasks()
    {
        const string URL = "https://api.harvestapp.com/v2/tasks";

        using (UnityWebRequest www = UnityWebRequest.Get(URL))
        {
            www.SetRequestHeader("user-agent", "MyApp (max@benmiller.com)");
            www.SetRequestHeader("Authorization", "Bearer " + AccessToken);
            www.SetRequestHeader("Harvest-Account-Id", AccountID);

            www.Send();

            while (!www.isDone)
            {
                
            }
            new WaitUntil(www.isDone);
            if (www.isHttpError)
            {
                Debug.LogError("UnityWebError: " + www.error);
                return null;
            }
            else
            {

                string Value = www.downloadHandler.text;

                TaskList JsonData = JsonUtility.FromJson<TaskList>(Value);
                return JsonData;
            }
        }

    }

    [Serializable]
    public class TaskList
    {
        public List<Task> tasks;
    }
    [Serializable]
    public class Task
    {
        public int id;
        public string name;
        public bool billable_by_default;
        public string default_hourly_rate; // No clue what type this should be.
        public bool is_default;
        public bool is_active;
        public DateTime created_at;
        public DateTime updated_at;
    }

Hi.

I had a similar task with 2 cases.

Case 1: I was receiving a KeyValuePair json and to save it as intended I was in need to save the response as a Dictionary<> and not a List<> (to make sure that keys and values match). So Instead of using Unity’s JSONUtility I was using MiniJSON(click for redirect) that works perfect inside coroutines and able to be saved as a Dictionary<>. Example:

public Dictionary<string, object> categories = new Dictionary<string, object>();

public IEnumerator GetJson()
{
        //not familiar with SendRequestHeader so I'm using old WWWForms
        WWWForm form = new WWWForm();
        form.AddField("user-agent", user_agent);
        form.AddField("auth-token", token);
        form.AddField("account-id", accountId);

        var uwr = UnityWebRequest.Post(url_api, form);

        yield return uwr.SendWebRequest();

        if (uwr.isNetworkError || uwr.isHttpError)
        {
            Debug.LogFormat("Error downloading file: <color=red>{0}</color> | Error code: <color=red>{1}</color>", uwr.downloadHandler.text, uwr.error);
        }
        else
        {

            var jsonResponce = MiniJSON.Json.Deserialize(uwr.downloadHandler.text) as Dictionary<string, object>;
            //saving data to a variable
            categories = jsonResponce;
        }
}

Case 2: Same as case 1 but the json was a mess and was using Unity’s JSONUtility. The idea was to do 2 coroutines. First coroutine was UWR request. In this you’re getting the response and saving it to a variable (without decoding). Second coroutine is the one that were waiting for first to finish and than decode the response. Example:

    private string uwr_response = ' ';
    private bool isLoaded = false;
    
    private void Start()
    {
             LoadJson();
    }
//this coroutine to get the response
    public IEnumerator GetJson()
     {
             isLoaded = false;
             //not familiar with SendRequestHeader so I'm using old WWWForms
             WWWForm form = new WWWForm();
             form.AddField("user-agent", user_agent);
             form.AddField("auth-token", token);
             form.AddField("account-id", accountId);
     
             var uwr = UnityWebRequest.Post(url_api, form);
     
             yield return uwr.SendWebRequest();
     
             if (uwr.isNetworkError || uwr.isHttpError)
             {
                 Debug.LogFormat("Error downloading file: <color=red>{0}</color> | Error code: <color=red>{1}</color>", uwr.downloadHandler.text, uwr.error);
             }
             else
             {
                 uwr_response = uwr.downloadHandler.text;
                 isLoaded = true;
             }
     }
    
    //this one to wait for response and decode
    private IEnumerator WaitingForJson()
        {
            while (!isLoaded)
                yield return new WaitForSeconds(0.1f);
    
            TaskList.DecodeJson(uwr_response);
        }
    
    //this one to be called when you need the json (probably in Start() method)
    private void LoadJson()
    {
            StartCoroutine(GetJson());
            StartCoroutine(WaitingForJson());
    }
    
    [Serializable]
    public class TaskList
    {
            public void DecodeJson(string json)
            {
                  TaskList packedData = JsonUtility.FromJson<TaskList>(json);  
            }
    }