【问题标题】:JavaScript - merging results from two API callsJavaScript - 合并两个 API 调用的结果
【发布时间】:2021-06-25 22:52:57
【问题描述】:

我有一个简单的 Angular 组件 (Ionic),它可以:

  1. 获取一些数据的 API 调用(作为 Observable 返回)和
  2. 从存储在设备上的 SQLite 数据库获取数据(作为 Promise 返回)

我正在尝试合并这两个结果。

这是我的组件:

import { Component, OnInit, Output } from '@angular/core';
import { merge } from 'rxjs';
import { Fact } from '../fact';
import { Label } from '../label';
import { DashboardService } from '../services/dashboard.service';
import { DatabaseService } from '../services/database.service';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.page.html',
  styleUrls: ['./dashboard.page.scss'],
})
export class DashboardPage implements OnInit {
  rows: Fact[];
  labels: Label[];

  constructor(
    private dashboardService: DashboardService,
    private database: DatabaseService
  ) {
    this.refreshDashboard();
  }

  ngOnInit() {}

  refreshDashboard() {
    console.log('refreshing...');
    this.getDashboardData();
    // Get labels
    this.database
      .createDatabase()
      .then(() => {
        this.getLabels();
      })
      .then(() => {            
        console.log(this.rows.length); // ******* UNDEFINED *******
        console.log(this.labels.length); // ******* UNDEFINED *******
      });
  }

  // Coming from an API call, which returns an Observable
  getDashboardData() {
    this.dashboardService.getData().subscribe((data) => {
      this.rows = data;
    });
  }

  // Coming from local SQLite database
  getLabels() {
    this.database
      .getLabels()
      .then((data) => {
        this.labels = [];
        if (data.rows.length > 0) {
          for (let i = 0; i < data.rows.length; i++) {
            this.labels.push(data.rows.item(i));
          }
        }
      })
      .catch((e) => {
        alert('There was an error: ' + e);
      });
  }

  // mergeResults()
}

我无法弄清楚如何确保在 mergeResults() 中使用这两个变量 rowslabels 之前已填充它们。

【问题讨论】:

  • 你需要 return 承诺,并使它们成为同一链的一部分。
  • 我的服务(数据库:DatabaseService)中的 getLabels() 函数返回承诺。我在组件的 getLabel() 方法中使用它来填充标签变量。如果我在模板中使用 *ngIf,我可以检查这两个变量是否已被填充。需要弄清楚如何在课堂上检查它们。我希望我说得通。
  • 但是组件中的 getLabels 方法(是的,这令人困惑)不返回承诺,调用它的回调也不返回,因此它不是 refreshDashboard 中承诺链的一部分。

标签: angular typescript promise rxjs


【解决方案1】:

then() 必须在顺序重要时嵌套。所以

  dosomething1.then( ()=> {
     dosomething2.then( () => {
       dosomething3.then( () => {
         console.log("hey");
                       })
                     })
                   })
                

在你的情况下,这意味着

 refreshDashboard() {
    console.log('refreshing...');
    this.getDashboardData();
    // Get labels
    this.database
      .createDatabase()
      .then(() => {
        this.getLabels();
      })
      .then(() => {  <---This here has no use at all. Nothing returns a promise here           
      });
  }

  // Coming from an API call, which returns an Observable
  getDashboardData() {
    this.dashboardService.getData().subscribe((data) => {
      this.rows = data;
    });
  }

  // Coming from local SQLite database
  getLabels() {
    this.database
      .getLabels()
      .then((data) => {
        this.labels = [];
        if (data.rows.length > 0) {
          for (let i = 0; i < data.rows.length; i++) {
            this.labels.push(data.rows.item(i));
          }
        }
        console.log(this.rows.length); // here you expect values to be ready
        console.log(this.labels.length); // here you expect values to be ready
      })
      .catch((e) => {
        alert('There was an error: ' + e);
      });

【讨论】:

  • 非常感谢!我犯了一些概念上的错误。非常感谢。
  • .then not 是否必须嵌套,那样你最终会回到“回调地狱”。您可以将第一个示例重写为dosomething1.then(() =&gt; dosomething2).then(() =&gt; dosomething3).then(() =&gt; console.log("hey")),这样更平易近人;关键是从回调中返回承诺,使其成为链的一部分。
  • @jonrsharpe 您能否提供一个使用该技术的顺序 http 调用的具体示例?不是一般的返回承诺,请解释如何进行 http 调用并将承诺返回到下一个。谢谢
  • 不要只是在已经存在的then-closure 中执行.then,而是按照@jonrsharpe 的建议返回函数调用。 会将承诺返回到下一个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-19
  • 1970-01-01
  • 2015-08-15
  • 1970-01-01
  • 2014-03-03
  • 1970-01-01
相关资源
最近更新 更多