【问题标题】:Fire callback after two separate successful http requests在两个单独的成功 http 请求后触发回调
【发布时间】:2016-03-07 05:13:13
【问题描述】:

我的应用程序的根组件在初始化时从我的服务中调用两个异步函数来获取数据。我想知道它们都完成后如何调用一个函数。我正在使用 angular 2.0.0-alpha.44 和 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.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')
    );
}

【问题讨论】:

标签: javascript angular typescript rxjs


【解决方案1】:

一个简单的仍然并行的解决方案是这样的:

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

此示例将并行运行两个可观察对象,并在它们都完成后将结果合并为一个结果。

【讨论】:

  • Angular2 使用 RxJS(并且 http-service 返回一个 Observable)。所以这个问题最好表述为“如何等待多个可观察对象完成?”
  • 啊,我明白了,等一下。
  • 用如何使用 RxJS 的示例更新了答案。
  • 非常感谢!这正是我想要的。我只需要像这样导入 RxJS:import * as Rx from '@reactivex/rxjs/dist/cjs/Rx'
【解决方案2】:

您可以在函数定义中传递 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));

【讨论】:

  • 这行得通,但它会导致服务在彼此之后而不是并行运行。
  • 为什么这很重要?了解这一点可能有助于制定更好的答案。
  • 如果服务被并行调用而不是同步调用,那么从服务器下载数据的速度会更快,这总是一件好事。因此,最好并行调整它们。
  • 不一定 - 服务器同时运行两个进程,这可能会延迟响应时间。 DB 可能不得不进行延迟响应的并发调用。然后将带宽分成两个并发请求,理论上这也可以减慢一半以上。不要仅仅因为并发性 == 就认为更好。
【解决方案3】:

你可以嵌套你的函数调用。

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

【讨论】:

    猜你喜欢
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 2017-09-18
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多