简体   繁体   中英

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.

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
  2. The Metadataservice makes an HTTP call to the Backend to retrieve these metadata
  3. Backend returns the metadatas in JSON format
  4. MetadataService transmit the JSON to the TranslatorService
  5. TranslatorService make some translations within the JSON and returns an array to the MetadataService
  6. MetadataService returns the array to the 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.

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...

How should I do ?

edit : Here's is my 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

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.

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...

Solution 2 Actually, I still had the problem of having the child component instanciated before even the subscribe function load datas. I've been able to resolve this by doing a <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()

As described in 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.

So MetadataService should return an Observable of what returns this.translatorService.getTranslatedElements(body.data); or an Observable of undefined in case of body.data is empty.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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