Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous function returns async metadata (including result) instead of just result

I'm writing an API with .NET Core 3.1. This API has an asynchronous function called GetSomeProperty(), which I use in an endpoint (called Get).

When receiving the response from this endpoint, the results properties are "moved down" one layer, and wrapped in metadata from the asynchronous method, like this:

"results": [
    {
        "result": {//actual result here}
        "id": 1,
        "status": 5,
        "isCanceled": false,
        "isCompleted": true,
        "creationOptions": 0,
        "isFaulted": false
    },
    {
        "result": {//actual result here}
        "id": 2,
        "status": 5,
        "isCanceled": false,
        "isCompleted": true,
        "creationOptions": 0,
        "isFaulted": false
    }
]

I don't want these results to be wrapped in this "asynchronous" wrapper.

While keeping the method asynchronous, how can I return the task result, instead of an object containing the task result?

There are two reasons why I haven't used .Result:

  1. Using .Result is considered bad practice, as it can cause locks if the task hasn't yet completed.
  2. I couldn't figure out where to put it. It doesn't seem to fit anywhere, as far as I can tell.

Here is the code (please bear in mind this has been significantly diluted and simplified for example purposes):

[HttpGet]
public async Task<object> Get(string someParameter)
{   
    //Do stuff

    var things = BuildACollectionOfItems();
    var results = things.Select(x => x.IrrelevantThing).OrderBy(x => x.SomethingIrrelevant).Select(async x =>
    {
        return new
        {
            x.Id,
            SomeProperty = await GetSomeProperty(x.Id)
        };
    }).ToArray();

    return new
    {
        Results = ((IEnumerable<object>) results),
        SomeIrrelevantThing = someIrrelevantThing
    };
}

private async Task<bool> GetSomeProperty(int id)
{
    var somethingFromAServer = (await _thingProvider.GetThing()).TheProperty;

    //Do stuff here

    var thing = _context.Stuff.FirstOrDefault(x => x.Thing == somethingFromAServer);

    //Do some more stuff

    return thing.Stuff;
}
like image 381
Jessica Avatar asked Jul 15 '20 13:07

Jessica


People also ask

How does async function return a value?

To return values from async functions using async-await from function with JavaScript, we return the resolve value of the promise. const getData = async () => { return await axios.

Does an async function return a promise?

The behavior of async / await is similar to combining generators and promises. Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

What is an asynchronous function?

An asynchronous function is any function that delivers its result asynchronously – for example, a callback-based function or a Promise-based function. An async function is defined via special syntax, involving the keywords async and await . It is also called async/await due to these two keywords.

What is the return type of async await in C#?

Now, one condition is when we want to return void. We cannot use the await keyword when we want to return void from an asynchronous function. In the above example, CallProcess() is an asynchronous function and it's returning void.


Video Answer


1 Answers

Your Select returns IEnumerable<Task> (because it is passed an async function); you can use Task.WhenAll to wait for them all to complete, and unwrap the results:

[HttpGet]
public async Task<object> Get(string someParameter)
{   
    //Do stuff

    var things = BuildACollectionOfItems();
    var results = await Task.WhenAll(things
        .Select(x => x.IrrelevantThing)
        .OrderBy(x => x.SomethingIrrelevant)
        .Select(async x => new
        {
            x.Id,
            SomeProperty = await GetSomeProperty(x.Id)
        }));

    return new
    {
        Results = ((IEnumerable<object>) results),
        SomeIrrelevantThing = someIrrelevantThing
    };
}
like image 57
Johnathan Barclay Avatar answered Oct 22 '22 07:10

Johnathan Barclay