Ionic 3组件重复调用致SQL查询无限执行问题求助
It sounds like you're running into infinite SQL query execution because you might be triggering database calls directly from your template (e.g., via a method called in *ngFor), which gets re-run on every Angular change detection cycle. Additionally, your initial date fetching uses a SQLResultSetRowList instead of a proper array, which can cause unexpected change detection behavior. Let's fix this step by step.
Root Cause
If you were calling a method like getRecords(date) from your template to fetch records for each date, Angular will execute that method every time it runs change detection (which happens frequently). This creates an infinite loop: the method runs a query, updates the component state, triggers change detection, and the method runs again.
Solution: Fetch All Data Once in the Component Lifecycle
Instead of querying the database from the template, fetch all necessary data in ionViewDidLoad (which runs once when the view loads), structure it into a usable format, and then reference that data in your template.
Step 1: Update the Component Class (report.ts)
First, we'll fetch distinct dates, then fetch records for each date, and store everything in component properties. We'll use promises to handle the async flow:
import { Component } from '@angular/core'; import { NavController } from 'ionic-angular'; import { SqlProvider } from '../../providers/sql/sql'; // Adjust import path as needed @Component({ selector: 'page-report', templateUrl: 'report.html' }) export class ReportPage { dates: string[] = []; dateRecords: { [key: string]: any[] } = {}; // Maps date strings to their records constructor(public navCtrl: NavController, private sql: SqlProvider) {} ionViewDidLoad() { // First, fetch all distinct dates this.sql.query("SELECT DISTINCT date FROM walkInRecord").then(dateResult => { const dateRows = dateResult.res.rows; const recordFetchPromises = []; // Convert date rows to an array and prepare record fetch promises for (let i = 0; i < dateRows.length; i++) { const date = dateRows.item(i).date; this.dates.push(date); // Add a promise to fetch records for this date recordFetchPromises.push( this.sql.query("SELECT * FROM walkInRecord WHERE date = ?", [date]).then(recordResult => { const records = []; for (let j = 0; j < recordResult.res.rows.length; j++) { records.push(recordResult.res.rows.item(j)); } return { date, records }; }) ); } // Wait for all record queries to complete Promise.all(recordFetchPromises).then(results => { results.forEach(({ date, records }) => { this.dateRecords[date] = records; }); }); }); } }
Step 2: Update the Template (report.html)
Now, reference the pre-fetched data in your template using *ngFor on the dates array and the grouped dateRecords object:
<ion-content padding> <ion-list> <!-- Loop through each unique date --> <ion-item-group *ngFor="let date of dates"> <ion-item-divider color="light"> <h2>Date: {{ date }}</h2> </ion-item-divider> <!-- Loop through records for this date --> <ion-item *ngFor="let record of dateRecords[date]"> <p><strong>ID:</strong> {{ record.id }}</p> <p><strong>Name:</strong> {{ record.name }}</p> <!-- Add other fields from your walkInRecord table here --> </ion-item> </ion-item-group> </ion-list> </ion-content>
Optimized Approach: Single Query + Client-Side Grouping
To reduce database calls (more efficient for large datasets), fetch all records at once and group them by date in code:
ionViewDidLoad() { this.sql.query("SELECT * FROM walkInRecord").then(allResult => { const allRecords = []; for (let i = 0; i < allResult.res.rows.length; i++) { allRecords.push(allResult.res.rows.item(i)); } // Group records by date this.dateRecords = allRecords.reduce((groups, record) => { const date = record.date; if (!groups[date]) groups[date] = []; groups[date].push(record); return groups; }, {}); // Get sorted distinct dates this.dates = Object.keys(this.dateRecords).sort((a, b) => new Date(b) - new Date(a)); }); }
This approach uses one SQL query instead of N+1 queries (where N is the number of distinct dates), which is much more performant.
Key Takeaways
- Never call async database methods directly from your template—they'll run infinitely on change detection.
- Convert
SQLResultSetRowListto a plain array for reliable*ngForiteration. - Fetch and structure all data in component lifecycle hooks (like
ionViewDidLoad) before rendering.
内容的提问来源于stack exchange,提问作者AishApp

