JavaScriptのモダンな非同期処理を駆使して**「複数のデータソースから並列でデータを取得し、完了したものから順次Wijmo FlexGridに表示する」**という、高速かつユーザーフレンドリーな実装方法をまとめる。
1. バックエンドの準備 (@RestController
)
バックエンド側でJSON形式のデータを返すAPIエンドポイントが用意されていることを前提とする。
Spring Bootでは、以下のように@RestController
を用いて簡単に実装できる。
com/example/demo/controller/ApiController.java
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/customers")
public List<CustomerDto> getCustomers() {
// 顧客データを取得する重い処理(例: 1秒かかる)
// Thread.sleep(1000);
return customerService.findAll();
}
@GetMapping("/products")
public List<ProductDto> getProducts() {
// 製品データを取得する非常に重い処理(例: 3秒かかる)
// Thread.sleep(3000);
return productService.findAll();
}
}
3. フロントエンド実装: HTMLの準備
まず、Wijmoライブラリを読み込み、FlexGridをホストするためのdiv
要素をHTMLに配置する。
templates/grid-view.html
<!DOCTYPE html>
<html>
<head>
<title>Wijmo FlexGrid Parallel Loading</title>
<link href="https://cdn.grapecity.com/wijmo/5.20231.888/styles/wijmo.min.css" rel="stylesheet" />
<script src="https://cdn.grapecity.com/wijmo/5.20231.888/controls/wijmo.min.js"></script>
<script src="https://cdn.grapecity.com/wijmo/5.20231.888/controls/wijmo.grid.min.js"></script>
</head>
<body>
<h1>ダッシュボード</h1>
<h2>顧客リスト(読み込み時間: 短)</h2>
<div id="customerGrid" style="height: 300px; margin-bottom: 20px;"></div>
<h2>製品在庫(読み込み時間: 長)</h2>
<div id="productGrid" style="height: 300px;"></div>
<script>
// このセクションにJavaScriptコードを記述する
</script>
</body>
</html>
4. フロントエンド実装: JavaScriptによる並列・順次データバインド
複数のAPIリクエストを並列で実行し、完了したものから順次グリッドを更新するロジックを実装する。
Step 1: 共通化されたデータバインド関数の作成
まず、再利用性を考慮し、データ取得からバインドまでの一連の処理を一つの関数にまとめる。
/**
* 複数のWijmo FlexGridに対し、それぞれ対応するAPIからデータを並列で非同期に取得し、
* 【完了したものから順次】itemsSourceに設定する。
*
* @param {Array<object>} gridConfigs - グリッドとAPIの設定情報の配列
* @param {wijmo.grid.FlexGrid} gridConfigs[].grid - データ設定対象のFlexGridインスタンス
* @param {string} gridConfigs[].apiUrl - データ取得先のAPIのURL
*/
function bindDataToGridsSequentially(gridConfigs) {
// 1. まず、すべてのグリッドのローディング表示を開始する
gridConfigs.forEach(config => {
config.grid.itemsSource = []; // データソースを空にする
config.grid.isLoading = true; // Wijmoのローディング表示を有効化
});
// 2. 各グリッドに対して、データ取得処理を並列で開始する
// forEachはawaitしないため、ループはすぐに完了し、
// 各fetchはバックグラウンドで並列に実行される。
gridConfigs.forEach(config => {
fetch(config.apiUrl)
.then(response => {
if (!response.ok) {
// HTTPステータスが200番台でない場合はエラーとする
throw new Error(`API request failed for ${config.apiUrl} with status ${response.status}`);
}
return response.json();
})
.then(data => {
// ★成功した場合、即座に対応するグリッドのitemsSourceを更新
config.grid.itemsSource = data;
console.log(`[Success] Grid updated from ${config.apiUrl}`);
})
.catch(error => {
// ★失敗した場合も、即座にエラー処理を行う
console.error(`[Failure] Could not load data for grid from ${config.apiUrl}:`, error);
// ここで、対象グリッドの隣にエラーメッセージを表示するなどのUIフィードバックも可能
})
.finally(() => {
// ★成功・失敗にかかわらず、そのグリッドのローディング表示を解除する
config.grid.isLoading = false;
});
});
}
Step 2: 関数の呼び出し
ページの読み込み完了後、FlexGridのインスタンスを生成し、作成した共通関数を呼び出してデータロードを開始する。
// 上記のbindDataToGridsSequentially関数の定義に続けて記述
document.addEventListener('DOMContentLoaded', () => {
// 1. 各FlexGridのインスタンスを生成する
const customerGrid = new wijmo.grid.FlexGrid('#customerGrid', {
isReadOnly: true,
autoGenerateColumns: false,
columns: [
{ binding: 'id', header: '顧客ID' },
{ binding: 'name', header: '顧客名' },
{ binding: 'country', header: '国' }
]
});
const productGrid = new wijmo.grid.FlexGrid('#productGrid', {
isReadOnly: true,
autoGenerateColumns: false,
columns: [
{ binding: 'productName', header: '製品名' },
{ binding: 'stock', header: '在庫数' },
{ binding: 'price', header: '単価', format: 'c0' }
]
});
// 2. グリッドとAPIの組み合わせを定義した設定配列を作成する
const gridConfigs = [
{ grid: customerGrid, apiUrl: '/api/customers' },
{ grid: productGrid, apiUrl: '/api/products' }
];
// 3. 共通関数を呼び出して、データの並列ロードとバインドを開始する
console.log('各グリッドのデータロードを開始します...');
bindDataToGridsSequentially(gridConfigs);
});