0

I just start to learn angular and I found my company project has the following code:

currentCDFlow: CDCurrentFlowDTO;

this.currentCDFlow = await this.serivce.getCDMaster();

and the getCDMaster() code is

public async getCDMaster(): Promise<CDCurrentFlowDTO> {
    return await this.http.post<CDCurrentFlowDTO>(Constants.BASE_HREF + '/getCDMaster', null, this.RequestJson).toPromise().catch(err => { throw err });
  }

as getCDMaster() is returning Promise<CDCurrentFlowDTO> (a Promise object), why it can assign to object of CDCurrentFlowDTO? I expect it can only assign to object of Promise<CDCurrentFlowDTO>, but not just CDCurrentFlowDTO (without enclosed by Promise<...>).

As in java,

String a = new ArrayList<String>();

should have compile error...

Is this typescript feature?

user1169587
  • 1,104
  • 2
  • 17
  • 34
  • 1
    Yes, it's a TS feature. `await` unwraps the value returned by the Promise. If you don't use `await`, the result is still a promise and compilation will fail – David May 31 '20 at 08:50
  • Is this mean even the function signature said it will return a Promise<...> , but if the function implementation has the return await keyword, then the function return value is NOT a Promise, but the unwrapped resolved value? Then if I just have the function signature without the function implementation, I will expect it return a Promise and will fail?!! – user1169587 May 31 '20 at 09:02
  • 1
    `return await ...` returns a promise, even if it might seem counter intuitive. This is because `async` functions always return a Promise. Have a look here too: https://stackoverflow.com/questions/38708550/difference-between-return-await-promise-and-return-promise – David May 31 '20 at 09:23

3 Answers3

1

the reason is Promise. A promise is an object representing an asynchronous return or you can say, a promise of something. The reason your code works in the assignment is because of the await syntax behind the function call. The await syntax works with Promise<T> makes the execution wait for the promise to finish, or to eventually return the object they 'promise' and that is why it works...

Check this article out to better understand... https://www.positronx.io/angular-8-es-6-typescript-promises-examples/

Update

Okay lets use your code as a working example...you have the following function defined

public async getCDMaster(): Promise<CDCurrentFlowDTO> {
  return await this.http.post<CDCurrentFlowDTO>(Constants.BASE_HREF + '/getCDMaster', null, this.RequestJson).toPromise().catch(err => { throw err });
}

/*
and then you call it here...
*/

// First you declare the variable to be of type CDCurrentFlowDTO but your
// function will return a Promise<CDCurrentFlowDTO> so let us see how this
// works out...
currentCDFlow: CDCurrentFlowDTO;

/*
Since the await syntax will cause the function call to wait for the returning Promise to complete then having the call like below will work
*/
this.currentCDFlow = await this.serivce.getCDMaster();

/*
But if we were to call it without the await:
*/
this.service.getCDMaster() // we then expect the Promise<CDCurrentFlowDTO> to return

If we still want to execute asynchronously we can do this for example...

//...

currentCDFlow: CDCurrentFlowDTO;

this.service.getCDMaster().then((result) => {
  currentCDFlow = result;

  //if we log here we should see the value
  console.log(currentCDFlow);
});
// but if we log here we expect undefined because the Promise has not returned yet
console.log(currentCDFlow);

The async you have for you function definition is not necessary because any function that is defined as async will return a Promise and yet the return value is already a Promise and yet you await for it...you can define it like this instead

publicgetCDMaster(): Promise<CDCurrentFlowDTO> {
  return this.http.post<CDCurrentFlowDTO>(Constants.BASE_HREF + '/getCDMaster', null, this.RequestJson).toPromise().catch(err => { throw err });
}
Community
  • 1
  • 1
bloo
  • 1,416
  • 2
  • 13
  • 19
  • I already see your article, but the return value should be a Promise, not an object of currentCDFlow even after the asynchronous call is finished? I see await will return the value of resolve value, not a Promise, but the async keyword again wrap the result to Promise? – user1169587 May 31 '20 at 08:14
1

async/await syntax is what allows currentCDFlow to be set from the promise. This is a feature in ES6. Asynchronous functions are prefixed with the async keyword and await suspends the execution until the promise is fulfilled and will unwrap the returned value.

Chris Danna
  • 1,164
  • 8
  • 17
  • you mean the returned value is in fact object of curentCDFlow, not Promise? but I remember if see the keyword async, the returned value must be enclosed by a Promise...! – user1169587 May 31 '20 at 08:03
  • The returned value from `getCDMaster()` is a `Promise`, and the returned value from `await getCDMaster()` is a `CurrentCDFlow`. – Chris Danna May 31 '20 at 21:09
0

Answer to your original question

await

Using await unwraps the returned value from the promise.

So this line of code

this.currentCDFlow = await this.serivce.getCDMaster();

actually assigns the resolved Promise value from the method to this.currentCDFlow.

If you don't use await in the assignment, TS will complain since you are trying to assign a promise to a non promise object.

currentCDFlow: CDCurrentFlowDTO;
this.currentCDFlow = this.serivce.getCDMaster(); //TS error

Answer to your second question in your comment

async

When you declare a function with the async keyword, it will always return a Promise, no matter what you do inside (so including a return await ...).

Have a look here:

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.

Depending on which version of JS is used, it will either be handled natively by JS (starting from ES8) or in transpiled TS code.

So all functions below, for instance, will return a Promise. You can try them in your browser's console

async function test()
{
    return "value";
}

async function test2()
{
    return Promise.resolve("value");
}

async function test3()
{
    return await Promise.resolve("value");
}

console.log(test()); //Promise {<resolved>: "value"}
console.log(test2()); //Promise {<resolved>: "value"}
console.log(test3()); //Promise {<resolved>: "value"}

So return myPromise and return await myPromise are often the same, with some exceptions like try/catch blocks, as explained here.

David
  • 33,444
  • 11
  • 80
  • 118