更有条理的方式来打电话给Coroutines?

wei*_*_yu 3 c# unity-game-engine

在我的代码中,我需要在上一个完成后调用多个Web请求.例如:

void Init()
{
    StartCoroutine(FirstRequest());
}

IEnumerator FirstRequest()
{
    www = new WWW(my_url);
    yield return www;
    StartCoroutine(SecondRequest());
}

IEnumerator SecondRequest()
{
    www = new WWW(my_url);
    yield return www;
}
Run Code Online (Sandbox Code Playgroud)

如果函数体是巨大的,它很容易混淆和混乱,在Javascript中,有Promise,所以我可以这样做:

function init() {  
  return validateParams()
    .then(firstRequest)
    .then(SecondRequest)
    .then((result) => {
      console.log(result)
      return result
    })
}
Run Code Online (Sandbox Code Playgroud)

任何人都有一个线索如何扩展Coroutines所以我可以有类似的效果?

Pro*_*mer 5

这非常简单.只需使用yield return SecondRequest();yield return StartCoroutine( SecondRequest());.在yield该协程名称前或StartCoroutine应该让等待协程返回之前,继续在其下方执行其他代码.

例如,您有四个应该按顺序调用的协同程序函数:

IEnumerator FirstRequest()
{
    www = new WWW(my_url);
    yield return www;
}

IEnumerator SecondRequest()
{
    www = new WWW(my_url);
    yield return www;
}

IEnumerator ThirdRequest()
{
    www = new WWW(my_url);
    yield return www;
}

IEnumerator FourthRequest()
{
    www = new WWW(my_url);
    yield return www;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

void Init()
{
    StartCoroutine(doSequentialStuff());
}

IEnumerator doSequentialStuff()
{
    //Do first request then wait for it to return
    yield return FirstRequest();

    //Do second request then wait for it to return
    yield return SecondRequest();

    //Do third request then wait for it to return
    yield return ThirdRequest();

    //Do fourth request then wait for it to return
    yield return FourthRequest();
}
Run Code Online (Sandbox Code Playgroud)

编辑:

如果我只获得成功状态,那么如果我只进入下一个协程怎么办?喜欢www = new WWW(my_url); yield return www; if(!www.error) StartCoroutine(SecondRequest());

在这种情况下,您应该Action在协同程序函数中用作参数:

IEnumerator FirstRequest(Action<bool> reqStat)
{
    www = new WWW(my_url);
    yield return www;
    if (!string.IsNullOrEmpty(www.error))
        reqStat(false);
    else
        reqStat(true);
}

IEnumerator SecondRequest(Action<bool> reqStat)
{
    www = new WWW(my_url);
    yield return www;
    if (!string.IsNullOrEmpty(www.error))
        reqStat(false);
    else
        reqStat(true);
}

IEnumerator ThirdRequest(Action<bool> reqStat)
{
    www = new WWW(my_url);
    yield return www;
    if (!string.IsNullOrEmpty(www.error))
        reqStat(false);
    else
        reqStat(true);
}

IEnumerator FourthRequest(Action<bool> reqStat)
{
    www = new WWW(my_url);
    yield return www;
    if (!string.IsNullOrEmpty(www.error))
        reqStat(false);
    else
        reqStat(true);
}
Run Code Online (Sandbox Code Playgroud)

用法:

void Init()
{
    StartCoroutine(doSequentialStuff());
}

IEnumerator doSequentialStuff()
{
    bool reqStat = false;

    //Do first request then wait for it to return
    yield return FirstRequest((status) => { reqStat = status; });

    //Do second request then wait for it to return
    if (reqStat)
        yield return SecondRequest((status) => { reqStat = status; });

    //Do third request then wait for it to return
    if (reqStat)
        yield return ThirdRequest((status) => { reqStat = status; });

    //Do fourth request then wait for it to return
    if (reqStat)
        yield return FourthRequest((status) => { reqStat = status; });
}
Run Code Online (Sandbox Code Playgroud)