简体   繁体   中英

Return custom type in Promise

I had some JSON array like below and I got these JSON from service.

[{
    "id": 3,
    "name": "Arun"
}, {
    "id": 5,
    "name": "Barun"
}, {
    "id": 1,
    "name": "Joy"
}, {
    "id": 8,
    "name": "Suman"
}]

Now, I made a like below

class Person{
  id:number
  name:string

    deserialize(input) {
      this.id = input.id;
      this.name = input.name
      return this;
   }
}

Now, I had a service class from where I am getting JSON(Array/dictionary) with Promise and I send this Promise to my parsing function. My Parsing function is below

 private  parse(response:Promise<{}>):Promise<{}>{

    return new Promise((success,failure) =>{
        response.then((result) => {
            if (result instanceof Array || Array.isArray(result)){
                let rs1 = result.map((val) => new Person().deserialize(val)) 
                success(rs1);
            }else{
                success(new Person().deserialize(result))
            }
        },(err) => {
            failure(err)
        });
    });
}

Now, I have two function

  expectingObjectOfPerson(){
    //get the promise from service class
    let result = servicePromise//Promise from service class with JSON

    //now call parse function 
    this.parse(result)
    .then((response) => {

        //I knew that response is an object of Person in run time.
        let person = response as Person

        //log name of this person
        console.log(person.name) //no run time exception

        //log name of this person
        console.log(person.nam) //Error thrown by compiler

        //now if I do this 
        console.log(response.name) //no run time exception

        //if this 
        console.log(response.nam) //run time exception, also no error thrown from compiler


        /* Main problem is on here.
        * Is there any way that response could automatically inferred to Person */
    }, (error) => {
        Console.log(error);
    })

}

expectingArrayOfPerson(){
     //get the promise from service class
     let result = servicePromise//Promise from service class with JSON

     //now call parse function 
     this.parse(result)
     .then((response) => {

         //I knew that response is an object of Person in run time.
         let persons = response as Person[]

         //log name of this person
         console.log(persons.map((val) => val.name)) //no run time exception

         //log name of this person
         console.log(persons.map((val) => val.name)) //Error thrown by compiler

         //now if I do this 
         console.log(response.map((val) => val.name)) //no run time exception

         //if this 
         console.log(persons.map((val) => val.name)) //run time exception , also no error thrown from compiler


         /* Main problem is on here.
         * Is there any way that response could automatically inferred to array of Person */
     }, (error) => {
         Console.log(error);
     })
}

Is there any way that response could automatically inferred to Person object or array of Person depends on response ? I am new in Angular, any help will be appreciated.

I am using latest version of Typescript.

First, let's go over your service : you're creating a Promise, to handle another promise. That's repeating yourself.

Furthermore, you should use Observables, which are upgraded promises.

Finally, you're creating a new Person object everytime. Consider using a static method to deserialize.

This gives you :

export function parse(response: Promise<{}>): Observable<{}> {
  // Rx 6 : return fromPromise(response)
  return Observable.fromPromise(response)
    .map(result => {
      if (result instanceof Array || Array.isArray(result)) {
        return result.map((val) => Person.deserialize(val))
      } else {
        return Person.deserialize(result);
      }
    })
}

export class Person {
  id: number;
  name: string;

  public static deserialize(input: any): Person {
    const person = new Person();
    person.id = input.id;
    person.name = input.name;
    return person;
  }
}

Now you can use your two functions like this :

expectingObjectOfPerson(){
  this.parse(servicePromise) // Whatever it is
    .subscribe(personInstance => {
      console.log(personInstance);
      console.log(personInstance instanceof Person);
    }, error => console.log(error));
}

expectingArrayOfPerson(){
  this.parse(servicePromise) // Whatever it is
  .subscribe(persons => {
    for (const personInstance of persons) {
      console.log(personInstance);
      console.log(personInstance instanceof Person);
    }
  }, error => console.log(error));
}

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