【问题标题】:MEAN-Stack - Cannot read second SQL Table from serverMEAN-Stack - 无法从服务器读取第二个 SQL 表
【发布时间】:2019-05-06 08:24:50
【问题描述】:

我正在使用 MEANStack 开发一个 WebApp,使用 Sequelize 访问 SQL 数据库。我设法用下面的代码阅读了一个 SQL 表。不幸的是,当我尝试读取第二个 SQL 时,客户端出现以下错误(第一个答案后编辑)

Table: core.js:1673 ERROR TypeError: tableData.processTables.map is not a function at MapSubscriber.project (tables.service.ts:32)

tables.service.ts:32 的错误是:

        processTables: tableData.processTables.map(table => {

下面是客户端错误的样子: Table: core.js:1673 ERROR TypeError: tableData.processTables.map is not a function at MapSubscriber.project

这是我的代码(编辑)

tables-list.component.html

<mat-spinner *ngIf="isLoading"></mat-spinner>
  <h1 class="mat-body-2">Process List &nbsp; </h1>

  <mat-accordion multi="true" *ngIf="userIsAuthenticated && !isLoading">
    <mat-expansion-panel>
      <mat-expansion-panel-header>
        Process List
      </mat-expansion-panel-header>
  <table mat-table [dataSource]="processTables" matSort class="mat-elevation-z8" *ngIf="userIsAuthenticated">

      <!-- ProcessName Column -->
      <ng-container matColumnDef="ProcessName">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> ProcessName </th>
        <td mat-cell *matCellDef="let element"> {{element.ProcessName}} </td>
      </ng-container>

      <!-- PackageVersion Column -->
      <ng-container matColumnDef="PackageVersion">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> PackageVersion </th>
          <td mat-cell *matCellDef="let element"> {{element.PackageVersion}} </td>
        </ng-container>

      <!-- RobotType Column -->
      <ng-container matColumnDef="RobotType">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> RobotType </th>
        <td mat-cell *matCellDef="let element"> {{element.RobotType}} </td>
      </ng-container>

      <!-- PackagePath Column -->
      <ng-container matColumnDef="PackagePath">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> PackagePath </th>
        <td mat-cell *matCellDef="let element"> {{element.PackagePath}} </td>
      </ng-container>

      <!-- CreationTime Column -->
      <ng-container matColumnDef="CreationTime">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> CreationTime </th>
          <td mat-cell *matCellDef="let element"> {{element.CreationTime}} </td>
        </ng-container>

      <!-- Status Column -->
      <ng-container matColumnDef="Status">
          <th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th>
          <td mat-cell *matCellDef="let element"> {{element.Status}} </td>
        </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedprocessTablesColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedprocessTablesColumns;"></tr>
    </table>
  </mat-expansion-panel>
</mat-accordion>

    <br> <h1 class="mat-body-2">Applications List &nbsp; </h1>

tables-list.component.ts:

import { Component, OnInit, OnDestroy } from "@angular/core";
import { ProcessTable, ApplicationsTable } from "./tables.model";
import { PageEvent } from "@angular/material";

import { Subscription } from "rxjs";
import { TablesService } from "./tables.service";
import { AuthService } from "../auth/auth.service";

@Component({
  // We load the component via routing and therefore we do not need a selector
  selector: "app-tables",
  templateUrl: "./tables-list.component.html",
  styleUrls: ["./tables-list.component.css"]
}) // Turn class into component by adding @Component Decorator

export class TableListComponent implements OnInit, OnDestroy {
  processTables: ProcessTable[] = [];
  applicationsTables: ApplicationsTable[] = [];
  isLoading = false;
  totalTables = 0;
  tablesPerPage = 5;
  currentPage = 1;
  pageSizeOptions = [1, 2, 5, 10];
  displayedprocessTablesColumns: string[] = ["ProcessName", "PackageVersion", "RobotType", "PackagePath", "CreationTime", "Status" ];
  displayedApplicationsTablesColumns: string[] = ["ProcessName", "PackageVersion" ];
  userIsAuthenticated = false;
  userId: string;
  isAdmin: boolean;

  private tablesSub: Subscription;
  private authStatusSub: Subscription;

  constructor(
    public tablesService: TablesService,
    private authService: AuthService
  ) {}

  ngOnInit() {
    this.isLoading = true;
    this.tablesService.getProcessTables(this.tablesPerPage, this.currentPage);
    this.userId = this.authService.getUserId();
    this.tablesSub = this.tablesService
      .getTableUpdateListener()
      .subscribe((tableData: { processTables: ProcessTable[]; applicationsTables: ApplicationsTable[]; tableCount: number }) => {
        this.isLoading = false;
        this.totalTables = tableData.tableCount;
        this.processTables = tableData.processTables;
        this.applicationsTables = tableData.applicationsTables;
      });
    this.userIsAuthenticated = this.authService.getIsAuth();
    // console.log("Is authenticated: " + this.userIsAuthenticated);
    this.authStatusSub = this.authService
      .getAuthStatusListener()
      .subscribe(isAuthenticated => {
        this.userIsAuthenticated = isAuthenticated;
      });
  }

  onLogout() {
    this.authService.logout();
  }

  ngOnDestroy() {
    this.tablesSub.unsubscribe();
    this.authStatusSub.unsubscribe();
  }
}

Tables.service.ts:

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Subject } from "rxjs";
import { map } from "rxjs/operators";
import { Router } from "@angular/router";

import { environment } from "../../environments/environment";
import { ProcessTable, ApplicationsTable } from "./tables.model";

const BACKEND_URL = environment.apiUrl + "/tables/";

@Injectable({ providedIn: "root" })
export class TablesService {
  private processTables: ProcessTable[] = [];
  private applicationsTables: ApplicationsTable[] = [];
  private tablesUpdated = new Subject<{ processTables: ProcessTable[]; applicationsTables: ApplicationsTable[]; tableCount: number }>();

  constructor(private http: HttpClient, private router: Router) {}

  getProcessTables(tablesPerPage: number, currentPage: number) {
    const queryParams = `?pagesize=${tablesPerPage}&page=${currentPage}`;
    this.http
      .get<{ processTables: ProcessTable[]; applicationsTables: ApplicationsTable[]; maxTables: number }>(
        BACKEND_URL + queryParams
      )
      .pipe(
        map((tableData: { processTables: ProcessTable[]; applicationsTables: ApplicationsTable[]; maxTables: number }) => {
          console.log(tableData);
          console.log(tableData.processTables);
          console.log(tableData.applicationsTables);
          return {
            processTables: tableData.processTables.map(table => {
              return {
                ProcessName: table.ProcessName,
                PackageVersion: table.PackageVersion,
                RobotType: table.RobotType,
                PackagePath: table.PackagePath,
                CreationTime: table.CreationTime,
                Status: table.Status
              };
            }),
             applicationsTables: tableData.applicationsTables.map(table => {
              return {
                ProcessName: table.ProcessName,
                PackageVersion: table.PackageVersion,
                WorkflowsBelongingToProcess: table.WorkflowsBelongingToProcess,
                ApplicationsBelongingToWorkflow: table.ApplicationsBelongingToWorkflow
              };
            }),
            maxTables: tableData.maxTables
          };
        })
      )
      .subscribe(transformedTablesData => {
        this.processTables = transformedTablesData.processTables;
        this.tablesUpdated.next({
          processTables: [...this.processTables],
          applicationsTables: [...this.applicationsTables],
          tableCount: transformedTablesData.maxTables
        });
      });
  }

  getTableUpdateListener() {
    return this.tablesUpdated.asObservable();
  }
}

表格\model.ts:

export interface Table {
  ProcessName: string;
  PackageVersion: string;
  RobotType: string;
  PackagePath: string;
  CreationTime: string;
  Status: string;
}

export interface ApplicationsTable {
  ProcessName: string;
  PackageVersion: string;
  WorkflowsBelongingToProcess: string;
  ApplicationsBelongingToWorkflow: string;
}

后端\控制器\tables.js:

const sequelize = require("../sequelize");

const getProcessTables = (req, res) => {
  return sequelize
    .query("SELECT * FROM dbo.Process", { type: sequelize.QueryTypes.SELECT })
    .then(fetchedtables => {
      return {
        message: "Process table fetched from the server",
        processTables: fetchedtables,
        maxProcessTables: fetchedtables.length
      };
    });
};

const getApplicationsTables = (req, res) => {
  return sequelize
    .query("SELECT * FROM dbo.Applications", {
      type: sequelize.QueryTypes.SELECT
    })
    .then(fetchedtables => {
      return {
        message: "Applications Table fetched from the server",
        applicationsTables: fetchedtables,
        maxApplicationsTables: fetchedtables.length
      };
    });
};

exports.getAllTables = (req, res) => {
  return Promise.all([
    getApplicationsTables(req, res),
    getProcessTables(req, res)
  ]).then(tables => {
    res.status(200).json({
      applicationsTables: tables[0],
      processTables: tables[1]
    });
  });
};

后端\路由\tables.js:

const express = require("express");

const TableController = require("../controllers/tables")

const router = express.Router({ mergeParams: true });

router.get("", TableController.getAllTables);

module.exports = router;

我该如何解决? 非常感谢 热纳罗

【问题讨论】:

  • @GeraintAnderson 有什么想法吗?

标签: sql node.js angular sequelize.js mean-stack


【解决方案1】:

我可以看到两个错误。

  • 您正在查询/tables/ 路由但未定义路由。
  • 您创建了两个请求处理程序并使用了相同的路由。所做的是请求转到第一个 app.get 块。不是第二个。

因此,首先您需要将 getProcessTable 和 getApplicationTable 合并为一个合并函数。

const sequelize = require("../sequelize");

const getProcessTables = (req, res) => {
  return sequelize.query("SELECT * FROM dbo.Process", { type: sequelize.QueryTypes.SELECT})
  .then(fetchedtables => {
    return {
      message: "Process table fetched from the server",
      processTables: fetchedtables,
      maxProcessTables: fetchedtables.length
    };
  });
};

const getApplicationsTables = (req, res) => {
  return sequelize.query("SELECT * FROM dbo.Applications", { type: sequelize.QueryTypes.SELECT})
  .then(fetchedtables => {
    return {
      message: "Applications Table fetched from the server",
      applicationsTables: fetchedtables,
      maxApplicationsTables: fetchedtables.length
    };
  });
};

exports.getAllTables = (req, res) =>{
    return Promise.all([getApplicationsTables(req,res), getProcessTables(req,res)])
    .then(tables =>{
        res.status(200).json({
            applicationsTables: tables[0],
            processTables: tables[1]
          });
    })
}

然后可能将其路由到表

router.get("/tables/", TableController.getAllTables);

现在,您需要更改map 行。

processTables: tableData.processTables.map 将是,

processTables: tableData.processTables.processTables.map(table => {

【讨论】:

  • 嗨@Aritra,感谢您的超级回复。我已经实施了您的更改,并相应地编辑了我的原始帖子。它还不起作用,实际上现在我也无法再读取过程数据表了。我发布了错误以及附加的图像。如您所见,至少在tables.service中读取了ProcessTable,但ApplicationTable是“未定义的”(tables.service的第28和29行的控制台日志)它可能是什么?谢谢,G。
  • 我的代码中有错字。我输入了applicationTables 而不是applicationsTables..(注意S)。编辑答案。
  • 嗨@Aritra,感谢您的回复。这太神奇了,因为现在我们可以读取这两个表。但是错误并没有消失。请查看我上面更新的代码以及我更新的屏幕截图,您可以在其中看到相同的错误,但您也可以看到现在两个表都已读取。目前两个表都没有加载。这个问题的原因是什么?
  • 那是因为您正在迭代父对象。 Map 是一个数组的函数。现在,table.applicationTables 是一个对象。所以你需要做table. applicationsTables.applicationsTables.map,编辑答案
  • 嗨@Aritra Chakraborty 有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多