【问题标题】:Await async function in typescript在打字稿中等待异步函数
【发布时间】:2018-05-03 00:10:18
【问题描述】:

我最近进入了 Angular2,我来自 c# 背景。我目前正在客户端中执行“数据服务层”,自然我正在按照我在 ac# 项目中的方式进行操作......(所以,如果我做错了什么,也请告诉我)。

我的结构是这样的:

  1. 数据服务 DataService(将来自 WS 的响应映射到指定类型 T 的通用数据服务)。这包括 get、post 和 put 函数。

  2. 博客服务 BlogService 扩展了 DataService,这将是例如 BlogListComponent 将使用的服务。

我还将使用 rgnx-store,但我暂时不考虑这个问题。

现在是代码。

这是来自 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);
    }

尝试 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;
    }

这里发生的是,我可以看到 DataService 设法将响应映射到一组博客文章,但是

return blogPosts;

被踩到之前

b => blogPosts = b

所以我只返回一个空数组。

尝试 2:这是异步的本质,所以我会通过使用 await 关键字告诉函数等待 Promise 返回来逃脱。

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

然后编译器给出一个巨大的错误,说我不能将博客文章数组作为异步函数中的返回类型。

尝试 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;
}

这和代码看起来一样好 - 一点也不!虽然我可以看到 GetBlogPosts 在异步函数返回任何内容之前没有命中它的 return 语句,但我认为我正在接近某些东西。

无论如何,我很可能在这里做一些根本错误的事情。我希望我能听到你是如何实现类似的东西的。

感谢一个沮丧的新手!

【问题讨论】:

    标签: typescript es6-promise


    【解决方案1】:

    尝试 2:这是异步的本质,所以我会通过使用 await 关键字告诉函数等待 Promise 返回来逃脱。

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

    然后编译器给出一个巨大的错误,说我不能将博客文章数组作为异步函数中的返回类型。

    对——因为 async 函数总是返回一个 Promise,所以如果 GetBlogPosts 是 async 那么它必须返回 Promise&lt;Array&lt;BlogPost&gt;&gt;,而不是 Array&lt;BlogPost&gt;。

    当然,使用 GetBlogPosts 的东西必须知道如何通过 promise 异步处理从它那里获取数据。

    您希望传播异步结果,直到您处于处理结果是异步事实的层,这通常意味着代码的入口点(事件处理程序等)。此时,您将使用非async 函数、then(处理成功)和catch(处理错误)。所以GetBlogPost 是那个位置,或者它应该将承诺返回给它的调用者,以便它的调用者(或其调用者等)可以是那个位置。


    旁注:这里至少有一个,可能还有两个问题:

    protected async processResponse<T>(response : Observable<Response>) : Promise<T> {
        return response.map(response => this.extractJson(response))
            .toPromise()
            .catch(this.handleError);
    }
    
    1. 这可能是也可能不是问题,具体取决于this.handleError 所做的事情。如果它返回一个被拒绝的承诺,请跳到下面的#2。如果不是:通常,使用 Promise,您要么 返回链, 或 处理错误,但不能同时处理两者。如果您两者都做,请务必确保您不会将拒绝转换为不适当的解决方案。请记住,then 和 catch 处理程序会创建一个新的 Promise,该 Promise 会根据它们所做的事情来解决/拒绝。

    2. 当您在 async 函数中时,使用 promise 回调不是惯用的。要么从声明中删除async,要么使用await(可能还有try/catch)。

    如果你保留async,那么这样做可能更习惯:

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

    ...我们再次将错误处理留给调用者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-24
      • 1970-01-01
      • 2019-03-18
      • 1970-01-01
      • 2018-03-08
      • 2016-10-20
      • 1970-01-01
      • 2016-10-01
      相关资源
      最近更新 更多