Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refactor an async method

I am having a project where we have an action catalogue of sorts. At the core of each action, there can be one of more network calls. So, the core method appears something like the following:

public async Task<Result> evaluate(){
//some setup chunk
        try
        {
            responsefromUri = await requestManager.Post(resourceUri, "");
        }
            // The non-retryable exception will directly trickle up.
        catch (RetryableException exception)
        {
            return BuildFailedCheckResult(
                StatusCode.Abandoned,
                Check1 + " abandoned. Failed to read the response for resource: " + resourceUri + " with exception: " + exception.Message);
        }

        if (string.IsNullOrEmpty(responsefromUri))
        {
            return BuildFailedCheckResult(
                StatusCode.Failed,
                Check1 + " failed. Empty response for resource: " + resourceUri);
        }

        try
        {
            responseJson = JObject.Parse(responsefromUri);
        }
        catch (JsonReaderException e)
        {
            throw new InvalidOperationException(Check1 + " check failed parsing resource: " + resourceUri, e);
        }
// use responseJson to get data and process further
}

This chunk is there for every network call. I want to extract this out. Now, I can't do that because there is an await and to extract it I need an async method; but to return failed check result, I need an out variable which is not allowed in async methods. What would be the right way to refactor this code? Method gets annoyingly lengthy when there are multiple network calls.

like image 615
dknight Avatar asked Jan 23 '26 19:01

dknight


1 Answers

Just package up your 'further processing' into a Func, e.g.

public async Task<Result> evaluate(Uri resourceUri, Func<JObject, Result> action)
{
    string responsefromUri;

    try
    {
        responsefromUri = await requestManager.Post(resourceUri, "");
    }
        // The non-retryable exception will directly trickle up.
    catch (RetryableException exception)
    {
        return BuildFailedCheckResult(
            StatusCode.Abandoned,
            Check1 + " abandoned. Failed to read the response for resource: " + resourceUri + " with exception: " + exception.Message);
    }

    if (string.IsNullOrEmpty(responsefromUri))
    {
        return BuildFailedCheckResult(
            StatusCode.Failed,
            Check1 + " failed. Empty response for resource: " + resourceUri);
    }

    JObject responseJson;
    try
    {
        responseJson = JObject.Parse(responsefromUri);
    }
    catch (JsonReaderException e)
    {
        throw new InvalidOperationException(Check1 + " check failed parsing resource: " + resourceUri, e);
    }

    return action(responseJson);
}

Example Usage:

// Example Usage
public Task<Result> DoStuff() 
{
    Uri uri = new Uri("http://localhost");

    return evaluate(uri, jobject => {
        return new Result(jobject["result"]);
    });
}
like image 80
jamespconnor Avatar answered Jan 26 '26 11:01

jamespconnor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!