2017-05-16 2 views
2

Könnte jemand mit dem Fehler helfen„Fehler: Nicht abgefangene (in Versprechen): Typeerror: kann Eigenschaft‚Länge‘undefinierten lesen“

"Error: Uncaught (in promise): TypeError: Cannot read property 'length' of undefined 

TypeError: Cannot read property 'length' of undefined 
    at SomeComponent.webpackJsonp.805.SomeComponent.getBList (http://localhost:4200/1.chunk.js:23613:34) 
    at SomeComponent.webpackJsonp.805.SomeComponent.ngOnInit (http://localhost:4200/1.chunk.js:23610:14) 
    at checkAndUpdateDirectiveInline (http://localhost:4200/vendor.bundle.js:11957:19) 
    at checkAndUpdateNodeInline (http://localhost:4200/vendor.bundle.js:13336:17) 
    at checkAndUpdateNode (http://localhost:4200/vendor.bundle.js:13304:16) 
    at debugCheckAndUpdateNode (http://localhost:4200/vendor.bundle.js:13933:59) 
    at debugCheckDirectivesFn (http://localhost:4200/vendor.bundle.js:13874:13) 
    at Object.eval [as updateDirectives] (ng:///SeasonPageModule/SeasonPageComponent_Host.ngfactory.js:16:5) 
    at Object.debugUpdateDirectives [as updateDirectives] (http://localhost:4200/vendor.bundle.js:13859:21) 
    at checkAndUpdateView (http://localhost:4200/vendor.bundle.js:13271:14) 
    at callWithDebugContext (http://localhost:4200/vendor.bundle.js:14259:42) 
    at Object.debugCheckAndUpdateView [as checkAndUpdateView] (http://localhost:4200/vendor.bundle.js:13799:12) 
    at ViewRef_.detectChanges (http://localhost:4200/vendor.bundle.js:11368:63) 
    at RouterOutlet.activateWith (http://localhost:4200/vendor.bundle.js:32580:42) 
    at ActivateRoutes.placeComponentIntoOutlet (http://localhost:4200/vendor.bundle.js:31760:16) 
    at ZoneAwareError (http://localhost:4200/vendor.bundle.js:95038:33) 
    at resolvePromise (http://localhost:4200/vendor.bundle.js:94728:31) 
    at resolvePromise (http://localhost:4200/vendor.bundle.js:94713:17) 
    at http://localhost:4200/vendor.bundle.js:94762:17 
    at ZoneDelegate.invokeTask (http://localhost:4200/vendor.bundle.js:94502:35) 
    at Object.onInvokeTask (http://localhost:4200/vendor.bundle.js:5362:37) 
    at ZoneDelegate.invokeTask (http://localhost:4200/vendor.bundle.js:94501:40) 
    at Zone.runTask (http://localhost:4200/vendor.bundle.js:94378:47) 
    at drainMicroTaskQueue (http://localhost:4200/vendor.bundle.js:94660:35)" 

Ich versuche, die Werte einer inneren Anordnung von einem json zu erhalten Datei an eine Variable, die ich erstellt habe. Meine JSON-Datei hat das folgende Format.

JSON filename: file.json 
    { 
     "A":[ 
     { 
      "id": "123", 
      "title": "title of A", 
      "type": "asf", 
      "B": [ 
      { 
       "id": "1", 
       "title": "title1" 
      }, 
      { 
       "id": "2", 
       "title": "title2" 
      } 
      ] 
     ] 
    } 

Ich habe erstellt paar Modelle, um die Werte zu speichern

A.model.ts 
import {B} from './b.model'; 

export interface A { 

    type?; 

    id?; 

    title?; 

    b?: B[]; 

} 

B.model.ts 
export interface B { 

    id?; 

    title?; 

} 

Mein Service, der die json kehrt hat folgende

someService.service.ts 

import {A} from '../model/a.model'; 
constructor(private _http: Http, private _authService: AuthService) {} 

    get() { 
    return this._http.get('app/file.json') 
        .toPromise() 
        .then(res => <A[]> res.json().showList) 
        .then(A => { return A; }); 
    } 

In den component.ts ich geschrieben habe, die folgende Code.

<somename>.component.ts 

import { Component, OnInit } from '@angular/core'; 
import { Routes, Router } from '@angular/router'; 
import {Observable} from 'rxjs'; 

import {A} from '../../shared/model/a.model'; 
import {SomeService} from '../../shared/service/someService.service'; 
import {B} from '../../shared/model/b.model'; 
import {Location} from '@angular/common'; 

class AList implements A { 
    constructor(public title?, public id?, public type?, public bList?: B[]) {} 
} 
class BList implements B { 
    constructor(public title?, public id?) {} 
} 

@Component({ 
    selector: 'ms-season-page', 
    styleUrls: [], 
    template: require('./season-page.component.html') 
}) 
export class SomeComponent implements OnInit { 

    b: B = new BList(); 

    bArray: B[] = []; 

    aArray: A[]; 

    constructor(private router: Router, private someService: SomeService) { 
    } 

    ngOnInit() { 
    this.someService.get().then(a => this.aArray = a); 
    this.bArray = this.getBList(this.aArray); 
    } 

    getBList(aArray: AList[]): B[] { 
    let bList: B[] = []; 
    for(let j=0; j<aArray.length; j++) { 
     for (let i=0; i<aArray[j].seasonList.length; i++) { 
      let b = new BList(aArray[j].B[i].title, aArray[j].B[i].id); 
      bList.push(b); 
     } 
    } 
    return bList; 
    } 
} 

Kann mir jemand helfen zu sagen, was für einen Fehler ich mache? Oder gibt es eine Möglichkeit, die Array-Werte "B" zu erhalten.

Vielen Dank im Voraus.

+0

Wahrscheinlich besser geschrieben als 'this._http.get ('app/file.json'). Map (res => res.json(). ShowList) .toPromise()'. Die Konvertierung von "Observable" zu "Promise" wird als letztes beibehalten und der native beobachtbare Operator wird genutzt. –

+0

Hallo Neil Lunn, Ich habe versucht, wie Sie vorgeschlagen haben und dint machen einen großen Unterschied und Fehler ist immer noch der gleiche. Eigentlich ist mein Problem in 'getBList (aArray: AList []): B [] { lassen Sie bList: B [] = []; für (lassen Sie j = 0; j Krish

+1

Nun natürlich ist es ein Problem, da die '.get()' Methode immer noch "async" ist. Sie müssen "innerhalb" der '.then()' oder Kette ähnlich manipulieren. I.E Die nächste Codezeile ist ** nicht ** wartet auf die vorhergehende. –

Antwort

3

Das Problem ist, dass this.someService.get asynchron ist und Sie versuchen, das Ergebnis darauf zugreifen, als ob es synchron war:

this.someService.get().then(a => this.aArray = a); // This is asynchronous 
this.bArray = this.getBList(this.aArray); // This will be called before `this.aArray` is set to anything. Now `this.aArray` will be undefined 

Das Update ist this.aArray in dem Rückruf der asynchronen Methode zu verwenden:

this.someService.get().then(a => { 
    this.aArray = a; 
    this.bArray = this.getBList(this.aArray); // Now `this.aArray` will have some value provided `someService.get()` returns something 
}); 
+0

Sie haben Recht. Aber soneService.get() gibt keinen Wert zurück, wie Neil Lunn oben erklärt hat. – Krish

+0

'someService.get()' gibt ein Versprechen zurück, aber ob das Versprechen auf einen bestimmten Wert verrechnet wird, hängt von der Struktur der Daten ab, die von '_http.get ('app/file.json')' zurückgegeben werden. – Saravana

+0

Danke. Ich habe nichts in der service.ts geändert und ich habe nur eine Zeile in der Komponente hinzugefügt, wie Sie vorgeschlagen haben und es hat funktioniert. Vielen Dank. – Krish

-1

Diese res.json().showList ist falsch. json gibt ein Versprechen zurück. Ein Versprechen hat kein showList Mitglied.

Fix

   toPromise() 
       .then(res => res.json()) 
       .then(A => { return A.showList; }); 

Mehr

An assertions should not be considered without caution.

+0

Eigentlich habe ich nicht richtig modifizieren.Mein Service ist wie get() { return this._http.get ('app/file.json') .toPromise() .then (res => res.json(). A) .then (A => {zurück A;}); } Wenn ich dies benutze, könnte ich die Werte von 'A' (dh ID, Titel und Typ von A) bekommen, konnte aber nicht die Werte von B. – Krish

+0

Ich habe die gleiche Methode in einem anderen Szenario verwendet Das hat gut funktioniert. – Krish

Verwandte Themen