Reputation: 4174
Root component of my application on init call two asynchronous functions from my services to get data. I would like to know how to call a function after they are both completed. I am using angular 2.0.0-alpha.44 and typescript 1.7.3
import {Component, OnInit} from 'angular2/angular2';
import {ServiceA} from './services/A';
import {ServiceB} from './services/B';
@Component({
selector: 'app',
template: `<h1>Hello</h1>`
})
export class App {
constructor(
public serviceA: ServiceA,
public serviceB: ServiceB
) { }
onInit() {
// How to run a callback, after
// both getDataA and getDataB are completed?
// I am looing for something similar to jQuery $.when()
this.serviceA.getDataA();
this.serviceB.getDataB();
}
}
serviceA.getDataA
and serviceA.getDataB
are simple http get functions:
// Part of serviceA
getDataA() {
this.http.get('./some/data.json')
.map(res => res.json())
.subscribe(
data => {
// save res to variable
this.data = data;
},
error => console.log(error),
// The callback here will run after only one
// function is completed. Not what I am looking for.
() => console.log('Completed')
);
}
Upvotes: 4
Views: 1402
Reputation: 7246
A simple still parallel solution would be something like:
let serviceStatus = { aDone: false, bDone: false };
let getDataA = (callback: () => void) => {
// do whatver..
callback();
}
let getDataB = (callback: () => void) => {
// do whatver..
callback();
}
let bothDone = () => { console.log("A and B are done!");
let checkServiceStatus = () => {
if ((serviceStatus.aDone && serviceStatus.bDone) == true)
bothDone();
}
getDataA(() => {
serviceStatus.aDone = true;
checkServiceStatus();
});
getDataA(() => {
serviceStatus.bDone = true;
checkServiceStatus();
});
I personally use RxJS to get me out of sticky situations like this, might be worth looking at.
EDIT:
Given feedback that RxJS is actually being used:
let observable1: Rx.Observable<something>;
let observable2: Rx.Observable<something>;
let combinedObservable = Rx.Observable
.zip(
observable1.take(1),
observable2.take(1),
(result1, result2) => {
// you can return whatever you want here
return { result1, result2 };
});
combinedObservable
.subscribe(combinedResult => {
// here both observable1 and observable2 will be done.
});
This example will run both observables in parallel and combine the result into one result when they are both done.
Upvotes: 5
Reputation: 1851
You could nest your function calls.
EG:
function getDataA (callback) {
var dataA = {test:"Hello Data A"};
callback && callback(dataA);
}
function getDataB (callback) {
var dataB = {test:"Hello Data B"};
callback && callback(dataB);
}
getDataA(function (dataA) {
getDataB(function (dataB) {
console.log("Both functions are complete and you have data:");
console.log(dataA);
console.log(dataB);
});
});
Upvotes: 0
Reputation: 1788
You could pass getDataA and getDataB callbacks in their function definitions, then call whatever you want in order:
function getDataA(callback) {
// do some stuff
callback && callback();
}
function getDataB(callback) {
// do some stuff
callback && callback();
}
function toCallAfterBoth() {
// do some stuff
}
getDataA(getDataB(toCallAfterBoth));
Upvotes: 1