使用async await推迟执行块

时间:2017-10-17 15:49:13

标签: angular typescript asynchronous

在我的Angular组件中,我创建了一个异步方法,需要在数据服务中的方法返回一些数据后执行某些操作。我试图使用异步等待,但我不认为我对这个概念有很好的把握。这是我尝试编写的组件中的方法:

async redrawGrid(params: any) {
        let v;
        try {
            v = await this.innerGridService.loadAccountList()
        } catch (error) {
            // return error
        }
        // I need to execute this code after loadAccountList() returns data
        params.node.childFlower.setRowHeight( (this.globalRowCount * 46 ) + 48);
        this.gridOptions.api.onRowHeightChanged();
}

我的服务loadAccountList()中的方法返回并且可观察到:

...
@Injectable()
export class ClientListService { 
...
responseObject$: Observable<ResponseObject>;
...

}
loadAccountList() {
        this.logService.info('InnerGridService loadAccountList()');

        if (this.dataStore.responseObject) {
            this.refreshDataStore();
        }
        let token = this.authenticationService.getToken();
        let headers = new Headers({ 'netx.esf.AuthenticationService': token });
        let options = new RequestOptions({ headers: headers });

        this.http.get(`${this.baseUrl}`, options)
.map((response: Response) => response.json())
            .subscribe(
            (data: InnerGridResponse) => {
                this.formatData(data.response.accountlist);
                this.dataStore.InnerGridResponse = data;
                this.dataStore.responseObject = data.response;
                this._InnerGridResponse.next(Object.assign({}, this.dataStore).InnerGridResponse);
                this._responseObject.next(Object.assign({}, this.dataStore).responseObject);
                if (data.errorCode === 0 || data.errorCode === 90) { // success
                    this.logService.info('loadAccountList() success: ', data.errorCode);
                    this.clearError();
                } else { // error code from backend
                    this.logService.error('loadAccountList() errorCode: ', data.errorCode);
                    this.setError(this.message[0], data.errorCode);
                }
            },
            error => { // exception
                this.logService.error('loadAccountList() exception:', error);
                this.setError(this.message[0], error._body);
                // throw error;
            });

        return this.responseObject$;
}

3 个答案:

答案 0 :(得分:3)

请原谅我说,但这段代码需要重大修改。

您正在提交从一个流中获取数据并将其放入另一个流中的经典反模式。这就像从软管中倒水到桶中,然后尝试将水从桶中倒入另一个软管中。相反,只需连接软管,或者更好的是,只需将某人的软管交给您。

为了过度简化,一般服务不应订阅并尝试对可观察对象进行任何操作。通常在映射之后它应该返回它。订阅应在消费者(组件)中完成,可以是TS逻辑,也可以是使用async管道的模板。

我不会尝试重写你的服务,因为那里有太多我不理解的事情。基本骨架应该是:

locaAccountList(): Proimse<AccountList> {
  return this.http.get(URL)
    .map(response => response.json())
    .toPromise()
    .then(json => makeAccountListFromJson(json));
}

我使用toPromise重写了这个以返回一个promise而不是一个observable。这通常与this.http一起出现,它通常只返回一个只有一次发射的观察者。这样,您可以await结果。你不能await一个可观察者发射。 await是为了承诺。尝试await一个可观察者只会await 42

一旦您重新编写了服务,您的组件就可以说:

async redrawGrid(params: any) {
  await this.innerGridService.loadAccountList();

  // I need to execute this code after loadAccountList() returns data
  params.node.childFlower.setRowHeight( (this.globalRowCount * 46 ) + 48);
  this.gridOptions.api.onRowHeightChanged();
}

您(可能)不需要try,因为异步函数中的错误无论如何都会从底部流出并从函数返回被拒绝的承诺。顺便说一下,我不清楚你如何使用调用loadAccountList()的结果。

答案 1 :(得分:0)

如果您想等待直到检索到数据,请将订阅从服务移动到redrawGrid并添加代码以在subscribe回调方法中执行。

答案 2 :(得分:0)

可能最简单的解决方案是:

async redrawGrid(params: any) {
        let v;
        try {
            //notice .toPromise() part
            v = await this.innerGridService.loadAccountList().toPromise();
        } catch (error) {
            // return error
        }
        // I need to execute this code after loadAccountList() returns data
        params.node.childFlower.setRowHeight( (this.globalRowCount * 46 ) + 48);
        this.gridOptions.api.onRowHeightChanged();
}