2015-12-02 157 views
3

我的應用程序在init上的根組件調用兩個異步函數從我的服務中獲取數據。我想知道如何在完成後調用一個函數。我使用的角度2.0.0 alpha.44和打字稿1.7.3兩次單獨成功的http請求後的消息回調

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.getDataAserviceA.getDataB是簡單的HTTP GET功能:

// 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') 
    ); 
} 
+0

也許'$ q.all'會有所幫助。這是一個[很好的答案](http://stackoverflow.com/questions/14545573/angular-accessing-data-of-multiple-http-calls-how-to-resolve-the-promises)。 – adriancarriger

+1

使用[RxJS#forkJoin](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/forkjoin.md) –

回答

4

一個簡單的還是並行的解決辦法是這樣的:

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(); 
}); 

我個人使用RxJS讓我出這樣棘手的情況,可能是值得考慮的。

編輯:

鑑於反饋實際使用RxJS:

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. 
    }); 

這個例子將並行運行兩個觀測,結果合併成一個結果時,他們都做了。

+2

Angular2使用RxJS(並且http服務返回一個Observable)。所以這個問題會更好一些:「如何等待多個觀察對象完成?」 – Etse

+0

啊,我明白了,給我一下。 – Nypan

+0

用RxJS做的例子更新了答案。 – Nypan

1

你可以通過getDataA和getDataB回調中的功能定義,然後按順序調用任何你想要的:

function getDataA(callback) { 
    // do some stuff 
    callback && callback(); 
} 

function getDataB(callback) { 
    // do some stuff 
    callback && callback(); 
} 

function toCallAfterBoth() { 
    // do some stuff 
} 
getDataA(getDataB(toCallAfterBoth)); 
+0

這有效,但它會導致服務運行而不是平行。 – Nypan

+0

爲什麼這很重要?知道這可能有助於定製更好的答案。 – Brant

+0

如果服務是並行調用而不是同步調用,那麼數據將從服務器更快地下載,這總是一件好事。因此,最好並行地調整它們。 – Nypan

0

你可以嵌套你的函數調用。

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); 
    }); 
});