From my point of view is the excepted return type of async function wrong. Because when I declare a static function as async to use await to wait for a function which returns a promise Typescript forces me to return a Promise. With this behavior I'm not able to deasync a function like a db connection. Below you'll find an example.
TypeScript Version: 2.0.3
tsconfig.json*
{
"compilerOptions": {
"noImplicitAny": false,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"rootDir": "./src",
"module": "commonjs",
"target": "es6",
"outDir": "dist"
},
"filesGlob": [
"src/**/*.ts",
"src/app.ts"
],
"exclude": [
"node_modules",
"dist",
"doc",
"Gruntfile.js"
]
}
Code
// A *self-contained* demonstration of the problem follows...
function get(key:string): Promise<string> {
return new Promise<string>((resolve, reject) => {
setTimeout(() => {
resolve('my value');
}, 1000);
});
}
async function splitStringFromDB(key:string, delimiter: string): string[] {
var string = await get(key);
return string.split(delimiter);
}
console.log(splitStringFromDB('myKey', ' '));
Expected behavior:
No Compile errors
Actual behavior:
error TS1055: Type 'string[]' is not a valid async function return type.
With this behavior I'm not able to deasync a function like a db connection
async-await does not make asynchronous code synchronous. The result of an async function
is a Promise.
Correct me if I'm wrong but the await function lets the function wait until the promise is resolved.
So if I have a huge stack trace from the api endpoint to the database get request I've to pass promise after promise that I can use at the end the await call?
await does not pause the execution of the program until the function returns. all it does is it makes the rest of the code in the function execute after the promise is resolved.
so these two are equivalent:
async function f() {
var value = await bar();
return value;
}
function f() {
return bar().then((value) => value);
}
I know but when you add now to the async function a return type like string, then the compiler will print the error I mentioned
cause the function does not return a string
; the function returns a Promise<string>
.
The async
modifier is not part of the function signature, it is just a marker to tell the compiler you intend to use await
in it, just to make sure you meant to do so, as it changes the semantics of the function call. in a sense it is an implementation detail about the function body and not part of the signature. For instance, when the compiler generates a .d.ts file for an async function, the async
keyword is not added, rather it is a regular function that returns a Promise
. I should add that this is not unique to TS, but is also done in other languages that implement this feature.
I don't agree with you. Because during runtime this function returns me a string if I hook in with a debugger and not a promise...
I don't agree with you. Because during runtime this function returns me a string if I hook in with a debugger and not a promise...
Just run see the console. Its a promise :
I wrote some stuff a while back that needs updating but it that might help :rose:
thanks @basarat.
I found this thread while looking for the format of returning an async function. In case anyone else does the same:
export default async function Files(files: {
[name: string]: string
}): Promise<() => Promise<void>> {
return async () => {}
}
You return a promise that returns a function that returns a promise (that's a mouthful).
So, what if I want a synchronous flow of code inside a method that returns non promise type. Is the following correct to do?
public getUserByIdSync(userId: number): User {
let promisedUsers: User[];
(async () => {
await this.getUsers().toPromise<User[]>().then(users => promisedUsers = users);
})();
// Here users have been fetched and assigned, ?
...
return promisedUsers[0];
}
It would be nice if there was a non-promise identifier for async return types. A big part of the value of async/await is not having to think in promises. Something that marks the return value as being returned asynchronously would be nice...
async function getFoo():*String
const foo:*String = await getFoo()
You could still (obviously) assign the synchronous return value to a Promise if you don't want to await.
const foo:Promise<String> = getFoo()
(where * is some character that denotes the value as asynchronously returned)
I guess there'd also be an argument to omit the async
keyword since it's implied by the return type.
Just a thought :)
I understand that async
functions return a Promise
.
But it should be completely feasible for Typescript to rewrite
async function foo(): string {
as
function foo(): Promise<string> {
Furthermore, because Promise
s are automagically boxed/unboxed, this shouldn't pose any problems for legacy code written as such:
async function foo(): Promise<string> {
That code would automagically become
function foo(): Promise<Promise<string>> {
, which thanks to the magic of unboxing is the same as Promise<string>
.
I think the Typescript team should seriously consider such a proposal given that it's
a: more intuitive for beginners and pros alike
b: poses no backwards compatibility issues and requires 0 porting of existing code
I recently faced this issue, and to be honest, when you wait for someone/something and she/he arrive, you don't expect for anything else. Because the person (or the data) is already here (available).
Most helpful comment
It would be nice if there was a non-promise identifier for async return types. A big part of the value of async/await is not having to think in promises. Something that marks the return value as being returned asynchronously would be nice...
async function getFoo():*String
const foo:*String = await getFoo()
You could still (obviously) assign the synchronous return value to a Promise if you don't want to await.
const foo:Promise<String> = getFoo()
(where * is some character that denotes the value as asynchronously returned)
I guess there'd also be an argument to omit the
async
keyword since it's implied by the return type.Just a thought :)