1

I'm trying to make my own JSON Web Request Wrapper on top of UWR, so it is easier to debug and change all Network requests from one script instead of debugging and changing on each scene

But I don't know how to return a string from a coroutine, can anyone lend me a hand?

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

namespace Test
{
    public class JSONUtils : MonoBehaviour
    {
        public string GetJSON(string uri)
        {
            // How to return a string from RequestJSON?
            StartCoroutine(RequestJSON(uri));
        }

        private IEnumerator RequestJSON(string url)
        {
            using (UnityWebRequest www = UnityWebRequest.Get(url))
            {
                yield return www.SendWebRequest();

                if (www.isNetworkError || www.isHttpError)
                {
                    Debug.Log(www.error);
                }
                else
                {
                    yield return www.downloadHandler.text;
                }
            }
        }
    }
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
Chico3001
  • 1,853
  • 1
  • 22
  • 43

1 Answers1

3

But I don't know how to return a string from a coroutine, can anyone lend me a hand?

Don't make the function return anything. Just make it a void function and use the parameter to return the data. Also don't just return only the body of the request. It makes sense to return important debugging information like isNetworkError, isHttpError, and the error of the request string` otherwise you won't know when the request fail or the cause of the failure.

You can do this with Action or delegate but I will use delegate in this example because it's allows you to name the callack parameters.

For example, this what it looks like when delegate is used:

public delegate void ReqCallback(bool isNetworkError, bool isHttpError, string error, string body);

And what it looks like with Action:

public Action<bool, bool, string, string> ReqCallback;

Delegate is more descriptive in this case. Just use it as the parameter then call that delegate when the request is done.

Your JSONUtils script:

namespace Test
{
    public class JSONUtils : MonoBehaviour
    {
        public delegate void ReqCallback(bool isNetworkError, bool isHttpError, string error, string body);

        public void GetJSON(string uri, ReqCallback callback)
        {
            // How to return a string from RequestJSON?
            StartCoroutine(RequestJSON(uri, callback));
        }

        private IEnumerator RequestJSON(string url, ReqCallback callback)
        {
            using (UnityWebRequest www = UnityWebRequest.Get(url))
            {
                //Send request
                yield return www.SendWebRequest();
                //Return result
                callback(www.isNetworkError, www.isHttpError, www.error, www.downloadHandler.text);
            }
        }
    }
}

Usage:

JSONUtils jsonUtils = GetComponent<JSONUtils>();
string url = "yahoo.com";

jsonUtils.GetJSON(url, (isNetworkError, isHttpError, error, body) =>
 {
     Debug.Log("isNetworkError: " + isNetworkError);
     Debug.Log("isHttpError: " + isHttpError);
     Debug.Log("error: " + error);
     Debug.Log("body: " + body);

     if (isNetworkError || isHttpError)
         Debug.Log(error);
     else
         Debug.Log(body);
});

You can also move if (isNetworkError || isHttpError) into the JSONUtils class but I think it is better when placed outside that class. Finally, you can also use a class or struct as the parameter in the delegate instead of four different parameter datatypes.

Programmer
  • 121,791
  • 22
  • 236
  • 328