简体   繁体   English

Angular2异步调用

[英]Angular2 async calls

I'm facing a classic http race issue, but I'm not familiar enough with Angular2 and Observable to resolve my case. 我面临一个经典的http竞赛问题,但是我对Angular2和Observable的了解还不足以解决我的问题。

Here's a description of my bricks : 这是我的积木的描述:

[ FormComponent ]
    |    |
   1|    |6
    |    |
[ MetadataService ] <----4 & 5----> [ TranslatorService ]
    |    |
   2|    |3
    |    |
 [ Backend ]
  1. My form component asks to the MetadataService the metadatas of the form 我的表单组件向MetadataService询问表单的元数据
  2. The Metadataservice makes an HTTP call to the Backend to retrieve these metadata Metadataservice对后端进行HTTP调用以检索这些元数据
  3. Backend returns the metadatas in JSON format 后端以JSON格式返回元数据
  4. MetadataService transmit the JSON to the TranslatorService MetadataService将JSON传输到TranslatorService
  5. TranslatorService make some translations within the JSON and returns an array to the MetadataService TranslatorService在JSON中进行一些翻译,并将数组返回到MetadataService
  6. MetadataService returns the array to the FormComponent. MetadataService将数组返回给FormComponent。

The architecture seems simple but there's something wrong in the way I'm implementating this, as in the end in my view the metadata property is "undefined" and therefore *ngFor throws an error My first idea was to subscribe to the Observable in the component but I don't know how to deal with these Observables as I've got two services. 架构看起来很简单,但是我实现它的方式出了点问题,因为最终,我的元数据属性是“未定义的”,因此* ngFor抛出错误我的第一个想法是订阅组件中的Observable但是由于有两项服务,我不知道如何处理这些Observable。

From my opinion the problem comes from the 4th step : 我认为问题出在第四步:

MetadataService 元数据服务

getFormMetaData(folderId: string, context: string){
    let body = JSON.stringify({
                   folderId: folderId,
                   context: context
               });
    return this.http.post(this.uri, body, options)
                            .map( (res) => { 
                                    let body = res.json();
                                    if (body.data){
                                        return this.translatorService.getTranslatedElements(body.data);
                                    }
                                } 
                            );
}

It should return an Observable, but the map() method return the value of the TranslatorService, which is an array... 它应该返回一个Observable,但是map()方法返回TranslatorService的值,它是一个数组。

How should I do ? 我应该怎么做 ?

edit : Here's is my FormComponent : 编辑:这是我的FormComponent:

FormComponent FormComponent

@Component({
    template: `
        <dynamic-form controls="formMetadata | async"></dynamic-form>
    `,
    providers: [MetadataService]
})
export class CustomerFormComponent {

    formMetadata: any; 

    constructor(private metadataService: MetadataService) { }

    ngOnInit() {
        this.formMetadata = this.formMetadataService.getFormMetadata('FR75P00000012', 'UserInformation');
    }
}

And my TranslatorService : 还有我的TranslatorService:

TranslatorService 翻译服务

getTranslatedElements(metadata: any) {
    debugger; // It never breaks here
    let elements = [];

    metadata.forEach( (field) => { 
        ...
        elements.push(field);
    } ) 

    return elements;

}

Update : 更新:

Ok, I advanced a bit. 好吧,我进步了一点。 It seems the problem comes from my async pipe, that I use in the FormComponent template to pass data to a child component. 看来问题出在我的异步管道上,我在FormComponent模板中使用了该管道来将数据传递给子组件。

Should this child component handle this kind of asyncronous data in a particular manner too ? 该子组件是否也应该以特定的方式处理这种异步数据?

Solution How to waste hours to debug : forget to put your databinded properties inside brackets. 解决方案如何浪费时间进行调试:忘记将数据绑定属性放在方括号中。

<dynamic-form controls="formMetadata"></dynamic-form>

should be 应该

<dynamic-form [controls]="formMetadata"></dynamic-form>

That explains why DynamicFormComponent received a string as input... 这就解释了为什么DynamicFormComponent接收字符串作为输入...

Solution 2 Actually, I still had the problem of having the child component instanciated before even the subscribe function load datas. 解决方案2实际上,我仍然有一个问题,就是即使订阅功能加载数据,也要实例化子组件。 I've been able to resolve this by doing a <dynamic-form [controls]="formMetadata" *ngIf="formMetadata"></dynamic-form> 通过执行<dynamic-form [controls]="formMetadata" *ngIf="formMetadata"></dynamic-form>我已经能够解决此问题

I couldn't use the async pipe, it didn't work. 我无法使用异步管道,但无法正常工作。 I don't know when the async trigger within the parent template, but it seems to be after the child component constructor() and noOnInit() 我不知道父模板中的异步触发器何时触发,但是它似乎在子组件的constructor()和noOnInit()之后

As described in http://reactivex.io/documentation/operators/map.html http://reactivex.io/documentation/operators/map.html中所述

The Map operator applies a function of your choosing to each item emitted by the source Observable, and returns an Observable that emits the results of these function applications. Map运算符将您选择的功能应用于由源Observable发出的每个项目,并返回一个Observable,该Observable发出这些函数应用程序的结果。

So MetadataService should return an Observable of what returns this.translatorService.getTranslatedElements(body.data); 因此,MetadataService应该返回返回this.translatorService.getTranslatedElements(body.data);的Observable this.translatorService.getTranslatedElements(body.data); or an Observable of undefined in case of body.data is empty. 或在body.data为空的情况下未定义的Observable。

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

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