Well, you have multiple questions/problems here. I'll start with the easiest. How do you get an observable from a function/object? The answer is via observable of:
return of(data);
But you eluded to a larger problem, which is: how do you defer returning data until child observables emit their values? You are looking for forkJoin. Via the docs:
forkJoin will wait for all passed Observables to complete and then it will emit an array with last values from corresponding Observables. So if you pass n Observables to the operator, resulting array will have n values, where first value is the last thing emitted by the first Observable, second value is the last thing emitted by the second Observable and so on. That means forkJoin will not emit more than once and it will complete after that.
You also have several other problems. For example, you are never subscribing to this.getClientData() or this.otherData(). Observables are lazily executed. Code in your observable will not execute until something subscribes to it. From the docs:
The code inside Observable.create(function subscribe(observer) {...}) represents an "Observable execution", a lazy computation that only happens for each Observer that subscribes.
It also appears as though you are using pipe/map in an attempt to set a property on your data object. But you're never setting data.client or data.other, so they will always be empty.
So, putting it all together, here's what your code might look like, with simulated server latency to show that forkJoin waits for completion of both observables:
import { Injectable } from '@angular/core';
import { Observable, of, forkJoin } from 'rxjs';
import { delay } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class TestService {
getData(): Observable<ServerResponse> {
const allOperations = forkJoin(
this.getClientData(),
this.getOtherData()
);
const observable = Observable.create(function subscribe(observer) {
// Wait until all operations have completed
allOperations.subscribe(([clientData, otherData]) => {
const data = new ServerResponse;
// Update your ServerReponse with client and other data
data.otherdata = otherData.other;
data.client = clientData.client;
// Now that data is 100% populated, emit to anything subscribed to getData().
observer.next(data);
observer.complete();
});
});
// We return the observable, with the code above to be executed only once it is subscribed to
return observable;
}
getClientData() : Observable<any> {
return of({ client: 'Client 1' });
}
getOtherData(): Observable<any> {
// Fake server latency
return of({ other: 'Other data that takes a while to return from server...' })
.pipe(delay(2000));
}
}
export class ServerResponse {
client: string;
otherdata: string;
}
If you call getData() and subscribe to the observable, you will see that forkJoin works as intended and we have to wait 2 seconds for both child observables to complete and our observable to emit a value:
this.testService.getData().subscribe(data => {
console.log(data);
});
It seems that you might be new to RxJS / asynchronous programming. I suggest reading the excellent introduction to RxJs when you get a chance. It can be tricky at first but with practice this will come to be second nature.