如何用 Observable 填充 Angular Mat-Table

How can I populate Angular Mat-Table with Observable

我正在尝试从 AWS DynamoDB table 中提取数据并将其显示在 Angular Mat-Table 中。当我这样做时,创建的数组返回的长度为 0,即使其中有 12 个值。我相信这会阻止 Mat-Table 对数据源更改起作用并最终显示数据。

控制台结果

Observable {_isScalar: true, _subscribe: ƒ, value: Array(0)}
value: (12) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
_isScalar: true
_subscribe: ƒ (subscriber)
__proto__: Object

组件代码

constructor(private dynamoService: DataDynamoService) {
    let dataSource: Observable<Record[]> = 
this.dynamoService.getAllRecords();
    console.log(dataSource);
}

服务功能代码

getAllRecords(): Observable<Record[]> {
  let dynDoc = {
  TableName: "records-table",
  };

  let retData: Record[] = [];
  Auth.currentCredentials()
    .then(credentials => {
      const dynamoDB = new DynamoDB.DocumentClient({
        credentials: Auth.essentialCredentials(credentials),
        region: 'us-east-1',
      });

      dynamoDB.scan(dynDoc).promise()
        .then(function(data){
          for(let record of data.Items){
            let rec = {
              value1: rec.value1,
              value2: rec.value2,
              value3: rec.value3,
              value4: rec.value4
            }
            retData.push(rec);
           }
        })
  })
  return of(retData);
}

我期望 Array(12) 的长度,但收到的是 0

这是最终起作用的服务代码:

getAllRecords() {
  let dynDoc = {
    TableName: "my-table-name",
  };

  return Auth.currentCredentials()
    .then(credentials => {
      const dynamoDB = new DynamoDB.DocumentClient({
        credentials: Auth.essentialCredentials(credentials),
        region: 'us-east-1',
      });

      return dynamoDB.scan(dynDoc).promise()
        .then(data => {return of(data.Items);
        })
    })
}

retData 在 promise 完成后被填充,但函数不会等待它。所以它永远是 []

组件代码

_dataSource: any[] = []; <-- Data bound to mat-table

constructor(private dynamoService: DataDynamoService) {
    this.dynamoService.getAllRecords().then(data => { // <-- value on promise completion
      this._dataSource = data; // <-- set MatTable source to promise values
      console.log(data, this._dataSource);
    });
}

服务代码

getAllRecords(): Promise<Record[]> { // <-- Return a promise, not observable
  let dynDoc = {
  TableName: "records-table",
  };

  let retData: Record[] = [];
  return Auth.currentCredentials() // <--- return outer promise
    .then(credentials => {
      const dynamoDB = new DynamoDB.DocumentClient({
        credentials: Auth.essentialCredentials(credentials),
        region: 'us-east-1',
      });

      return dynamoDB.scan(dynDoc).promise() // <-- return inner promise 
        .then(function(data){
          for(let record of data.Items){
            let rec = {
              value1: rec.value1,
              value2: rec.value2,
              value3: rec.value3,
              value4: rec.value4
            }
            retData.push(rec);
           }

          return retData; // <-- return the data outside the loop, still inside promise
        })
  })
}

模板代码(组件)


<mat-table [dataSource]="_dataSource">

...

</mat-table>

如果 DynamoDB 可以选择使用可观察对象,我会切换到那个。

您可以使用 asyncawait 等待承诺。

async getAllRecords(): Observable<Record[]> {
    let dynDoc = {
        TableName: "records-table",
    };
    const credentials = await Auth.currentCredentials();

    const dynamoDB = new DynamoDB.DocumentClient({
        credentials: Auth.essentialCredentials(credentials),
        region: 'us-east-1',
    });

    let retData: Record[] = [];
    const data = await dynamoDB.scan(dynDoc).promise();
    for(let record of data.Items){
        let rec = {
        value1: rec.value1,
        value2: rec.value2,
        value3: rec.value3,
        value4: rec.value4
        }
        retData.push(rec);
    }

    return of(retData);
}

如果dynamoDB.scan(dynDoc) returns Observable 你可以简单地使用

async getAllRecords(): Observable<Record[]> {
    let dynDoc = {
      TableName: "records-table",
    };

    const credentials = await Auth.currentCredentials();

    const dynamoDB = new DynamoDB.DocumentClient({
      credentials: Auth.essentialCredentials(credentials),
      region: 'us-east-1',
    });

    return dynamoDB.scan(dynDoc).pipe(
      map(data =>
        data.map(rec => ({
          value1: rec.value1,
          value2: rec.value2,
          value3: rec.value3,
          value4: rec.value4
        }))
      )
    );
}