简体   繁体   English

等待打字稿中的异步功能

[英]Await async function in typescript

I've recently jumped into Angular2 and I come from ac# background. 我最近跳入Angular2,并且来自ac#背景。 I'm currently doing the "data service layer" within the client, and naturally I'm doing it the way I would in ac# project... (So if I'm doing something completely wrong, please let me know as well). 我目前正在客户端中执行“数据服务层”,很自然地我会按照在ac#项目中的方式进行操作...(因此,如果我做的事情完全错误,也请让我知道)。

I have a structure that is like this: 我有一个像这样的结构:

  1. Data service DataService (generic dataservice that will map the response from a WS to the specified type T). 数据服务DataService(将来自WS的响应映射到指定的类型T的通用数据服务)。 This consist of get, post and put functions. 这包括get,post和put函数。

  2. Blog service The BlogService extends the DataService, and this will be the service that for instance BlogListComponent will use. 博客服务BlogService扩展了DataService,这将是BlogListComponent将使用的服务。

I'm also going to use rgnx-store, but I will leave that out of this question for now. 我还将使用rgnx-store,但现在暂时不考虑这个问题。

Now to the code. 现在到代码。

This is from the DataService. 这是来自DataService。

protected post<T>(endpointUrl: string, request: object) : Promise<T> {
        return this.processResponse<T>(this.http.post(endpointUrl, JSON.stringify(request), this.options()));
    }

protected async processResponse<T>(response : Observable<Response>) : Promise<T> {
        return response.map(response => this.extractJson(response))
            .toPromise()
            .catch(this.handleError);
    }

Try 1: My first try - That I naturally thought would work but certainly didn't. 尝试1:我的第一次尝试-我自然以为可以,但肯定没有用。

public GetBlogPosts(request : GetBlogPostsRequest) : Array<BlogPost> {
        var blogPosts: Array<BlogPost> = [];

        super.post<Array<BlogPost>>(BlogDataService.GET_BLOGPOSTS_ENDPOINT, request).then(b => blogPosts = b);

        return blogPosts;
    }

What happens here is that I can see that the DataService manage to map the response to an array of blog posts, but the 这里发生的是,我可以看到DataService设法将响应映射到一系列博客文章,但是

return blogPosts;

is stepped into before 进入之前

b => blogPosts = b

So I simply return an empty array. 所以我只是返回一个空数组。

Try 2: This is the nature of async, so I would get away by telling the function to wait for the Promise to return by using the await keyword. 尝试2:这是异步的本质,所以我将通过使用await关键字告诉函数等待Promise返回而逃脱。

await super.post<Array<BlogPost>>(BlogDataService.GET_BLOGPOSTS_ENDPOINT, request).then(b => blogPosts = b);

And then the compiler gives a huge error saying I can't have an Array of blogposts as a return type within an async function. 然后,编译器给出了一个巨大的错误,说我不能在异步函数中将博客文章数组作为返回类型。

Try 3: Then I removed the async declaration of GetBlogPosts since I really want to return an Array of BlogPost instead of changing it to an Array of whatever, and added a nested function which is an async function. 尝试3:然后我删除了GetBlogPosts的异步声明,因为我真的想返回一个BlogPost数组,而不是将其更改为任何数组,并添加了一个嵌套函数,它是一个异步函数。

var s = () => super.post<Array<BlogPost>>(BlogDataService.GET_BLOGPOSTS_ENDPOINT, request).then(b => blogPosts = b);

async function awaiter(asyncFunction) : Promise<any> {
    await asyncFunction;
}

This worked as nicely as the code looks - not at all! 这和代码看起来一样好-根本没有! Though I could see that the GetBlogPosts didn't hit its return statement before the async function returned anything so I think I am getting closer to something. 虽然我可以看到GetBlogPosts在异步函数返回任何内容之前没有命中它的return语句,所以我认为我已经接近了。

Anyways, I am most likely doing something fundamentally wrong here. 无论如何,我最有可能在这里做一些根本错误的事情。 And I hope I can hear how you are implementing something similar to this. 我希望我能听到您如何实施与此类似的操作。

Thanks from a frustrated newbie! 感谢沮丧的新手!

Try 2: This is the nature of async, so I would get away by telling the function to wait for the Promise to return by using the await keyword. 尝试2:这是异步的本质,所以我将通过使用await关键字告诉函数等待Promise返回而逃脱。

 await super.post<Array<BlogPost>>(BlogDataService.GET_BLOGPOSTS_ENDPOINT, request).then(b => blogPosts = b); 

And then the compiler gives a huge error saying I can't have an Array of blogposts as a return type within an async function. 然后,编译器给出了一个巨大的错误,说我不能在异步函数中将博客文章数组作为返回类型。

Right — because an async function always returns a promise, so if GetBlogPosts is async then it has to return Promise<Array<BlogPost>> , not Array<BlogPost> . 正确—因为async函数总是返回promise,所以如果GetBlogPostsasync则它必须返回Promise<Array<BlogPost>>而不是Array<BlogPost>

Then of course, the thing using GetBlogPosts has to know how to handle getting the data back from it via the promise, asynchronously. 然后,当然, 使用 GetBlogPosts的东西必须知道如何处理通过promise从异步获取数据的方式。

You want to propagate the asynchronous result until you're at the layer that handles the fact the result is asynchronous, which usually means the entry point into your code (event handler, etc.). 您需要传播异步结果,直到到达处理结果是异步的层为止,这通常意味着代码的入口点(事件处理程序等)。 At that point, you'd use a non- async function, then (to handle success), and catch (to handle errors). 那时,您将使用一个非async函数, then (处理成功)并catch (处理错误)。 So either GetBlogPost is that spot, or it should return the promise to its caller so its caller (or its caller, etc.) can be that spot. 因此,要么GetBlogPost就是那个地点,要么它应该将诺言返回给其调用方,以便其调用方(或其调用方等)可以成为该地点。


Side note: There's at least one and possibly two issues here: 旁注:这里至少存在一个问题,并且可能有两个问题:

protected async processResponse<T>(response : Observable<Response>) : Promise<T> {
    return response.map(response => this.extractJson(response))
        .toPromise()
        .catch(this.handleError);
}
  1. This may or may not be an issue depending on what this.handleError does. 根据this.handleError功能,这可能是问题,也可能不是问题。 If it returns a rejected promise, skip to #2 below. 如果它返回被拒绝的承诺,请跳到下面的#2。 If not: Usually, with promises, you either return the chain, or handle errors, but not both. 如果不是,则:通常,使用诺言,您要么返回链, 要么处理错误,但不能同时执行。 If you do both, it's important to make sure you don't convert a rejection into an inappropriate resolution. 如果两者都做,那么确保不要将拒绝转换为不合适的分辨率非常重要。 Remember that then and catch handlers create a new promise, which is resolved/rejected based on what they do. 请记住, then catch处理程序会创建一个新的promise,该promise将根据它们的操作来解决/拒绝。

  2. As you're in an async function, using the promise callbacks isn't idiomatic. 当您处于async函数中时,使用promise回调并不是惯用的。 Either drop the async from the declaration, or use await (and possibly try / catch ). 从声明中删除async ,或使用await (并可能try / catch )。

If you keep the async , then it's probably more idiomatic to do this: 如果保持async ,则执行此操作可能更惯用:

protected async processResponse<T>(response : Observable<Response>) : Promise<T> {
    return await response.map(response => this.extractJson(response)).toPromise();
}

...where again we leave error handling to the caller. ...我们再次将错误处理留给调用者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM