2

In the following code, why is variable t assigned a correct task when neither of lambdas in the chain return such a type? The lambdas return task<http_response>, task<json::value> and none.

The code works when the last lambda returns task and when it returns nothing.

Any pointers to online docs that shed some light on it will be appreciated.

Thanks.

pplx::task<void> t = client.request(methods::GET, L"/api/dummy")
.then([](http_response response)
{
    if (response.status_code() == status_codes::OK)
    {
        response.content_ready().wait();
        return response.extract_json(); // return task<json::value>
    }
})

.then([](json::value value)
{
    if (value.has_field(L"id"))
    {
        int id = value.at(L"id").as_integer();
    }

    // t.wait() below works regardless if this  
    // line is commented out or not.
    //return pplx::task<void>({});
});

try
{
    t.wait();
}
catch (const std::exception &e)
{
    [...]
}
bdristan
  • 1,048
  • 1
  • 12
  • 36
  • well what is that `[...]`? it is the key of understanding what is hapenning here – David Haim Sep 11 '16 at 17:12
  • [...] represents a code that mainly does extraction of data from json - definitely no task of any kind created/returned there. I updated the post accordingly. – bdristan Sep 11 '16 at 17:58

1 Answers1

2

then always returns some kind of task, take a look here. if the callback supplied to then does not return anything then will just return task<void>. in a nut shell, then will return a task that correspond to the return type of the callable supplied to then

task<T> t1 = t0.then([]{ return T(); });
task<void> t2 = t3.then([]{ /*return nothing*/ });

let's break this to parts:

task<http_response> t0 = client.request(methods::GET, L"/api/dummy");
task<json::value value> t1 = t0.then(/*return json from response*/);
task<void> t = t1.then(/*extract "id", returns nothing*/);
t.wait();

now, take a look on what happens when you use co_await:

 auto response = co_await client.request(methods::GET, L"/api/dummy");
  if (response.status_code() == status_codes::OK)
    {
        response.content_ready().wait();
        auto value = co_await response.extract_json();
        if (value.has_field(L"id"))
        {
           int id = value.at(L"id").as_integer();
        }
    }

isn't it neat? the entire continuation chaining just collapsed to synchronous code, but the code is still asynchronous behind the scenes!

David Haim
  • 25,446
  • 3
  • 44
  • 78
  • Got it! I missed "The result type of the returned task is determined by what _Func returns" in the docs. Thanks. – bdristan Sep 11 '16 at 18:32