3

I've looked at similar questions on StackOverflow but none of them match my specific problem:

I have a TypeScript function in an Angular 6 service, calling a function in another service like this:

Service1:

myArray: Array<IMyInterface>

...

getArray(): Observable<IMyInterface[]> {

    this.myArray= this.service2.getAnArray(1);
    return Observable.of(this.myArray);
}

Service2

getAnArray(myEntityId): Array<IMyInterface> {
  const myArray2: IMyInterface[] = [];

  this.getConnection().then(connection => {
    connection.invoke('GetEntityById', myEntityId).then((someJson: any) => {
      someJson.forEach( x => myArray2.push(x));       
      return myArray2;
    })
  }); 
}

It gives me the error in Service2 A function whose declared type is neither 'void' nor 'any' must return a value.

I need to return myArray2 after connection.invoke('GetEntityById', myId) has resolved, as the array is only populated after that resolves, which is why I try to do it inside then.

How do I do this?

Chris Halcrow
  • 28,994
  • 18
  • 176
  • 206
  • may be you can add `myArray` on component instance like `this.myArray` and use it wherever you want in component rather than returning it? – user1608841 Aug 28 '18 at 04:08
  • return connection as well? – Nico Aug 28 '18 at 04:09
  • No, thanks but neither of those work. I've updated the question with more details of the context. The connection shouldn't be returned from Service2, as it's important that any use of it is strictly encapsulated in Service2 – Chris Halcrow Aug 28 '18 at 04:17
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – CollinD Aug 28 '18 at 04:45

2 Answers2

1

This may/may not suit your needs, but you could just return the Promise from your service method, eg:

getAnArray(myEntityId) {
  const myArray: IMyInterface[] = [];

  // Note the return here
  return this.getConnection().then(connection => {
    return connection.invoke('GetEntityById', myEntityId).then((someJson: any) => {
      someJson.forEach( x => myArray.push(x));       
      return myArray;
    })
  }); 
}

Your calling code would then look like

getAnArray(someId).then(function(theArray) {. . .});
CollinD
  • 7,304
  • 2
  • 22
  • 45
  • I think another `return` is missing before `connection.invoke`. – Matt McCutchen Aug 28 '18 at 04:21
  • No, getAnArray isn't a promise – Chris Halcrow Aug 28 '18 at 04:23
  • Then what you want to do isn't really possible I don't think. If you're relying on asynchronous behavior, I don't know of a graceful way to convert that to synchronous behavior for calling code outside of async/await which is just promises anyway. – CollinD Aug 28 '18 at 04:30
1

A bit late for this. But someone may find this helpful. You can use Async/Await for this. The reason is every time 'await' occurs, it will hold the thread until the job is done.

 async getAnArray(myEntityId) {
    await this.getConnection();
    try {
      let result = await connection.invoke('GetEntityById', myEntityId).then((someJson: any) => {
      someJson.forEach(x => myArray.push(x));
      return myArray;
      })
   } catch (err) {
  console.log(err);
}

}

To get results (will return a promise):

this.getAnArray(myEntityId).then((data) => {
  console.log('data' , data);
 
});