Real-Serious-Games / C-Sharp-Promise

Promises library for C# for management of asynchronous operations.
MIT License
1.19k stars 149 forks source link

How can I get response data at the first stage #97

Closed Syslos94 closed 5 years ago

Syslos94 commented 5 years ago

Hi there, I have some problem in using RestClient, and @jdnichollsc gave me a direction and told me that I should use promise. I found this issue, and tried it myself. But it seems I have no luck with it. So I came and seek help here.

I have defined a class:

public class A {
    public string A1;
    public string A2;
    public string A3;

   public IPromise<string> Get(string endpoint) {
     var uri = ip + endpoint + "/" + this.A1 + "/" + this.A2;
     var promise = new Promise<string>();
    RestClient.Get (uri, (err, res) => {
        promise.Resolve(res.Text);
    });
   }

   public void GetA3(endpoint) {
        var promise = Get (endpoint);
        promise.Done (result => Log (result ));
   }
}

At another place, I do this

A a = new A();
A.A1= "a1";
A.A2= "a2";
A.GetA3("endpoint");
print(A.A3);

I got an output here which show A.A3 is null, but what I want is "a3". I debug the code, find it will do print(A.A3) first, then Log (result ).

Could you please give me some advice to help me get the correct result? Thank you!

adamsingle commented 5 years ago

It doesn't look like you ever assign anything to A3. Your method GetA3 should either assign it or return the result. But it looks like you are just logging it out. As you said, you are seeing Log(result) so you know the promise is resolving. You just need to assign it to A3 at that same place.

public void GetA3(endpoint)
{
    var promise = Get(endpoint);
    promise.Done(result => 
    {
        Log(result);
        A3 = result;
    });
}

or you could return the result from GetA3 and assign it later. Either way.

adamsingle commented 5 years ago

And don't forget you error handling :)

Syslos94 commented 5 years ago

Thanks for your reply, but what I am trying to say is the order is wrong, it should run Log() first then print().

I have found someone else who has the same problem. So currently, I'm using HttpWebRequest to send GET request instead.

Anyway, thank you for your help :)

adamsingle commented 5 years ago

The order is correct. You GetA3() logs asynchronously, when your rest endpoint returns a value, while your print() runs synchronously right after calling GetA3(). If you did

public IPromise GetA3(endpoint) 
{
    var returnPromise = new Promise();
    var promise = Get (endpoint);
    promise.Done(result => 
    {
        Log (result );
        returnPromise.Resolve();
    }
    return returnPromise;
}

A a = new A();
A.A1= "a1";
A.A2= "a2";
A.GetA3("endpoint")
.Then(() =>
{
    print(A.A3);
});

then your print() call would show after the Log() because you are chaining it to the back of the promises resolution.

This is a very convoluted example to show you. But the point is you are calling print() before the promise has resolved and called Log() The link you show with the person having the same issue also has responses explaining this same thing. You have to be aware of the difference between asynchronous code (which will resolve at a later time) and synchronous code which will execute immediately. You example here is a perfect case of that. Log() will not be called until RestClient.Get (uri, (err, res) => returns and your promise is resolved. Breakpoints will show you this behaviour also. If you put a breakpoint on promise.Resolve(res.Text); inside of your Get() method and another on print() you'll see the order they resolve in.

Syslos94 commented 5 years ago

@adamsingle Thanks mate, it really works for me. Really appreciate.

adamsingle commented 5 years ago

my pleasure

jdnichollsc commented 5 years ago

Thanks @adamsingle for your help, @ssSolars now you can close this issue 👍