Unity 将UnityWebRequest改为async/await异步

发布时间 2023-08-01 15:47:35作者: Jason_c

花了一点时间,对UnityWebRequest进行了简单封装,使用起来更方便一些,顺便实现了post接口轮询、重试的功能

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;

public static class WebRequest
{
    public class Result
    {
        public long code;
        public string message;
        public byte[] data;

        public string GetText()
        {
            if (data != null && data.Length != 0)
            {
                return Encoding.UTF8.GetString(data, 0, data.Length);
            }
            return "";
        }
    }
    public class LoopArgs
    {
        /// <summary>
        /// 循环多少次,为0时表示无限循环
        /// </summary>
        public ushort Count { get; private set; }
        /// <summary>
        /// 每次循环间隔多少毫秒
        /// </summary>
        public ushort MsDelay { get; private set; }
        /// <summary>
        /// 直到返回true时终止循环,该方法允许根据每次结果,设置终止循环的时机,在小于循环次数时提前结束循环
        /// </summary>
        public Func<Result, bool> AbortUntil { get; private set; }
        public LoopArgs(ushort count, ushort msDelay, Func<Result, bool> abortUntil)
        {
            Count = count;
            MsDelay = msDelay;
            AbortUntil = abortUntil;
        }
    }
    public static async Task<Result> Post(string url, WWWForm form, Dictionary<string, string> headers)
    {
        using (UnityWebRequest request = UnityWebRequest.Post(url,form))
        {
            if (headers != null)
            {
                foreach (KeyValuePair<string, string> item in headers)
                {
                    request.SetRequestHeader(item.Key, item.Value);
                }
            }
            await request.SendWebRequest();
            Result result = new Result();
            result.code = request.responseCode;
            result.message = request.result.ToString();
            result.data = request.downloadHandler.data;
            return result;
        }
    }
    public static async Task<Result> Post(string url, WWWForm form, Dictionary<string, string> headers, LoopArgs loopArgs = null)
    {
        return await Loop(() => { return Post(url, form, headers); }, loopArgs);
    }
    static async Task<Result> Loop(Func<Task<Result>> request, LoopArgs loopArgs)
    {
        Result result;
        if (loopArgs == null)
        {
            result = await request();
        }
        else
        {
            ushort i = 0;
            while (true)
            {
                result = await request();
                if (loopArgs.AbortUntil != null && loopArgs.AbortUntil.Invoke(result))
                {
                    break;
                }
                if (loopArgs.Count != 0 && i >= loopArgs.Count)
                {
                    break;
                }
                await Task.Delay(loopArgs.MsDelay);
                i++;
            }
        }
        return result;
    }


    /// <summary>
    /// 异步的扩展方法
    /// </summary>
    public static TaskAwaiter GetAwaiter(this UnityWebRequestAsyncOperation asyncOp)
    {
        var tcs = new TaskCompletionSource<object>();
        asyncOp.completed += obj => { tcs.SetResult(null); };
        return ((Task)tcs.Task).GetAwaiter();
    }
}

 

这样调用

using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        Debug.LogError("开始请求");
        PostTest();
        Debug.LogError("调用结束");
    }
    async void PostTest()
    {
        Debug.LogError("开始");
        WebRequest.Result result = await WebRequest.Post("www.baidu.com", null, null, new WebRequest.LoopArgs(3, 1000, (r) => { Debug.LogError(r.message); return false; }));
        string content = result.GetText();
        Debug.LogError("结束: " + content);
    }

}

 

打印结果: